java8新特性中lambda表达式的使用

       最近工作中使用到了lambda表达式,不是很理解,就去学习了一下,通过了解发现真的特别好用。就像下面这样,几行代码完成了java8之前很多行才能完成的任务量。下面的代码是基于groovy语言实现的,这次主要通过举例总结一下java8中lambda的新特性,文章最后拿在公司一个业务场景进行实战,给小伙伴提供一个使用lambda表达式迅速解决现实问题的思路。

一、基础介绍

1、lambda替换匿名类

之前匿名内部类这样写的:

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("aa");
            }
        }).start();

现在使用lambda表达式很简便:

new Thread(() -> System.out.println("lambda expression rock !!")).start();

注意:虽然两者可以互相实现,lambda和匿名内部类有区别:this指代的上下文不一样,内部类时,创建了一个新的范围,通过实例化具有相同名称的新局部变量,可以从封闭范围覆盖局部变量值。但是lambda的this是外部的,执行完以后不会覆盖外部局部变量,没有副作用,不修改外部变量的值。

2、使用lambda对列表进行迭代

之前遍历时经常需要for循环,很多行代码,现在使用lambda就变得简单了。

List features = Arrays.asList("aaa", "bbb", "ccc");
features.forEach(n -> System.out.println(n));

也可以这样使用方法引用。

features.forEach(System.out::println);

多使用方法引用;后者通常可读性更高并且代码会简短。

3、使用lambda表达式和函数式接口Predicate

(1)先声明一个filter(List<String> names, Predicate condition)方法。

    private static void filter(List<String> names, Predicate condition) {
        for (String name : names) {
            if (condition.test(name)) {
                System.out.println(name + " ");
            }
        }
    }

(2)使用该方法进行过滤操作。

List<String> languages = Arrays.asList("java", "python", "groovy");
System.out.println("Language which starts with j:");
filter(languages, (str) -> ((String) str).startsWith("j"));
System.out.println("Language which ends with n:");
filter(languages, (str) -> ((String) str).endsWith("n"));
System.out.println("Language all:");
filter(languages, (str) ->(true));
System.out.println("length less 5");
filter(languages,(str -> ((String)str).length()<5));

(3)上面可以实现将符合条件的过滤出来输出,但是我们使用lambda表达式更简单。

Predicate<String> startWithJ = (n) ->n.startsWith("j");
Predicate<String> lessFiveLong = (n) -> n.length()<5;
languages.stream().filter(startWithJ.and(lessFiveLong)).forEach(
        n-> System.out.println(n)
);

(4)Predicate<T>接口是一个函数式接口,函数式接口就是只定义一个抽象方法的接口,如上面的Runnable接口,还有下面的也是函数式接口。

public interface Comparator<T> {
int compare(T o1, T o2);
}

Lambda表达式允许你直接以内联的形式为函数式接口的抽象方法提供实现,并把整个表达式作为函数式接口的实例。

4、获取数字的个数、最小值、最大值、总和以及平均值。

List<Integer> primes = Arrays.asList(2, 3, 5, 7, 11, 13, 17, 19, 23, 29);
IntSummaryStatistics stats=primes.stream().mapToInt((x)->x).summaryStatistics();
System.out.println(stats.getMax());
System.out.println(stats.getAverage());

5、使用distinct() 对集合进行去重

List<Integer> numbers = Arrays.asList(9, 10, 3, 4, 7, 3, 4);
List<Integer> distinct = numbers.stream().map(i -> i * i).distinct().collect(Collectors.toList());
System.out.println(distinct);
System.out.printf("original list: %s,Square Without duplicates:%s %n", numbers, distinct);

6、使用map将对象进行转换。

(1)打印输出所有转换后的值。

List<Integer> costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
costBeforeTax.stream().map((cost) -> cost +cost + .12*cost).forEach(System.out::println);

(2)计算转换后值的和。

double bill = costBeforeTax.stream().map((cost) -> cost + .12 * cost).reduce((sum, cost) -> sum + cost).get();

(3)可以使用lambda表达式的parallel方法对数据进行并行处理

double bill2 = costBeforeTax.stream().parallel().map((cost) -> cost + .12 * cost).reduce((sum, cost) -> sum + cost).get();

Lambda的并行流虽好,但也要注意使用场景。如果平常的业务处理比如过滤,提取数据,没有涉及特别大的数据和耗时操作,则真的不需要开启并行流。就像上面这个例子,本来就没几个数,在并行时开启线程花的时间都比循环多了。

(4)使用filter进行过滤,新集合每个元素符合过滤原则

List<Integer> filtered = costBeforeTax.stream().filter(x -> x > 200).collect(Collectors.toList());
System.out.printf("Original List : %s, filtered list : %s %n", costBeforeTax, filtered);

(5)将符合条件的集合用逗号连接,综合使用lambda表达式各种方法

String result = costBeforeTax.stream().filter(x -> x > 200).map(x -> "jiankang" + x).collect(Collectors.joining(", "));
System.out.println(result);

7、lambda更强大的操作

以住需要定义多个变量,编写数十行甚至数百行的代码的集合操作,现在都基本简化成了可以在一行之内完成,就像下面的例子,之前我们需要各种for循环遍历,判断条件是否符合,集合add方法操作进入不同的键值里面,使用lambda表达式更简单。

(1)先准备一些数据。

Student student=new Student("男","xiao1");
Student student1=new Student("女","xiao2");
Student student2=new Student("男","xiao3");
Student student3=new Student("男","xiao4");
Student student4=new Student("男","xiao15");
List<Student> students=Arrays.asList(student,student1,student2,student3,student4);

(2)将list集合转换为流,然后使用collect方法收集以性别分组的数据保存到map中。

Map<String,List<Student>> studentsMap = students.stream().collect(Collectors.groupingBy(Student::getSex));

(3)测试输出语句:

System.out.println(studentsMap.toString());
for(String list:studentsMap.keySet()){
            System.out.println(studentsMap.get(list));
            for(Student string:studentsMap.get(list)){
                System.out.println(string.toString());
            }
        }

(4)输出结果如下。

{女=[Student{sex='女', name='xiao2'}], 男=[Student{sex='男', name='xiao1'}, Student{sex='男', name='xiao3'}, Student{sex='男', name='xiao4'}, Student{sex='男', name='xiao15'}]}
[Student{sex='女', name='xiao2'}]
Student{sex='女', name='xiao2'}
[Student{sex='男', name='xiao1'}, Student{sex='男', name='xiao3'}, Student{sex='男', name='xiao4'}, Student{sex='男', name='xiao15'}]
Student{sex='男', name='xiao1'}
Student{sex='男', name='xiao3'}
Student{sex='男', name='xiao4'}
Student{sex='男', name='xiao15'}

二、实战案例

1、背景

公司有个需求是根据人汇总每个月的报税信息,这个功能本来上线了,同事做的,她第一步拿到每个月的数据,遍历所有数据,放入map中,map的键是人的唯一标识,值是该人这个月的报税信息,第二步遍历每个map的值进行金额相加得到每个人的汇总信息。现在又需要细分月度汇总的维度,根据人,税目,公司进行分别汇总,这个场景使用lambda就比较简单了,先按照人分组,再按照公司分组,最后按照税目分组,拿到一个map,最后进行汇总计算。为了复现这个场景,第一步生成测试数据,第二步进行汇总

2、测试数据生成

(1)报税信息Bean

  1. tax_type 税目
  2. document_property 公司主体
  3. lectrue  人唯一编码
  4. sum_money 每条记录的金额


import java.math.BigDecimal;

public class DataRecord {
    private Integer id;
    private String tax_type;
    private String document_property;
    private BigDecimal sum_money;
    private Integer lecture;

    public DataRecord(Integer id, String tax_type, String document_property, BigDecimal sum_money, Integer lecture) {
        this.id = id;
        this.tax_type = tax_type;
        this.document_property = document_property;
        this.sum_money = sum_money;
        this.lecture = lecture;
    }


    @Override
    public String toString() {
        return "DataRecord{" +
                "id=" + id +
                ", tax_type='" + tax_type + '\'' +
                ", document_property='" + document_property + '\'' +
                ", sum_money=" + sum_money +
                ", lecture=" + lecture +
                '}';
    }
}

3、生产数据Utils


import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class DataUtils {

    public static String[] taxs = new String[]{"稿酬所得", "劳务报酬所得", "特许权使用费所得"};
    public static String[] documentPropertys = new String[]{"A公司", "B公司"};
    public static int[] lectures = new int[]{100, 101, 102, 103};


    public static List<DataRecord> getDatas() {
        List<DataRecord> list = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            list.add(new DataRecord(i, taxs[i % 3], documentPropertys[i % 2], new BigDecimal(i), lectures[i % 4]));
        }
        return list;
    }

}

4、最后我们使用lambda表达式进行汇总

(1)主要是这段代码,我streamr方法将数据写入流中,然后使用filter方法过滤掉税目,主体,人唯一编码为空的问题数据,最后使用collect()方法进行数据收集,在collect方法中,我们先按照人唯一编码使用groupingBy方法进行分组,然后将分组的数据再使用groupingBy方法按照主体分组,最后将二次分组的数据再按照税目使用groupingBy方法分组,结束以后就获取了一个分好组的大map。

        //根据tax documentProperty ,lecture 分组
        Map<Integer, Map<String, Map<String, List<DataRecord>>>> bigMap = list.stream().filter(it ->
                it.getDocument_property() != null && it.getLecture() != null && it.getTax_type() != null
        ).collect(Collectors.groupingBy(DataRecord::getLecture, Collectors.groupingBy(DataRecord::getDocument_property, Collectors.groupingBy(DataRecord::getTax_type))));

(2)bigMap长这样,map套map

{100={A公司={稿酬所得=[DataRecord{id=0, tax_type='稿酬所得', document_property='A公司', sum_money=0, lecture=100}, DataRecord{id=12, tax_type='稿酬所得', document_property='A公司', sum_money=12, lecture=100}, DataRecord{id=24, tax_type='稿酬所得', document_property='A公司', sum_money=24, lecture=100}, DataRecord{id=36, tax_type='稿酬所得', document_property='A公司', sum_money=36, lecture=100}, DataRecord{id=48, tax_type='稿酬所得', document_property='A公司', sum_money=48, lecture=100}, DataRecord{id=60, tax_type='稿酬所得', document_property='A公司', sum_money=60, lecture=100}, DataRecord{id=72, tax_type='稿酬所得', document_property='A公司', sum_money=72, lecture=100}, DataRecord{id=84, tax_type='稿酬所得', document_property='A公司', sum_money=84, lecture=100}, DataRecord{id=96, tax_type='稿酬所得', document_property='A公司', sum_money=96, lecture=100}], 特许权使用费所得=[DataRecord{id=8, tax_type='特许权使用费所得', document_property='A公司', sum_money=8, lecture=100}, DataRecord{id=20, tax_type='特许权使用费所得', document_property='A公司', sum_money=20, lecture=100}, DataRecord{id=32, tax_type='特许权使用费所得', document_property='A公司', sum_money=32, lecture=100}, DataRecord{id=44, tax_type='特许权使用费所得', document_property='A公司', sum_money=44, lecture=100}, DataRecord{id=56, tax_type='特许权使用费所得', document_property='A公司', sum_money=56, lecture=100}, DataRecord{id=68, tax_type='特许权使用费所得', document_property='A公司', sum_money=68, lecture=100}, DataRecord{id=80, tax_type='特许权使用费所得', document_property='A公司', sum_money=80, lecture=100}, DataRecord{id=92, tax_type='特许权使用费所得', document_property='A公司', sum_money=92, lecture=100}], 劳务报酬所得=[DataRecord{id=4, tax_type='劳务报酬所得', document_property='A公司', sum_money=4, lecture=100}, DataRecord{id=16, tax_type='劳务报酬所得', document_property='A公司', sum_money=16, lecture=100}, DataRecord{id=28, tax_type='劳务报酬所得', document_property='A公司', sum_money=28, lecture=100}, DataRecord{id=40, tax_type='劳务报酬所得', document_property='A公司', sum_money=40, lecture=100}, DataRecord{id=52, tax_type='劳务报酬所得', document_property='A公司', sum_money=52, lecture=100}, DataRecord{id=64, tax_type='劳务报酬所得', document_property='A公司', sum_money=64, lecture=100}, DataRecord{id=76, tax_type='劳务报酬所得', document_property='A公司', sum_money=76, lecture=100}, DataRecord{id=88, tax_type='劳务报酬所得', document_property='A公司', sum_money=88, lecture=100}]}}, 101={B公司={稿酬所得=[DataRecord{id=9, tax_type='稿酬所得', document_property='B公司', sum_money=9, lecture=101}, DataRecord{id=21, tax_type='稿酬所得', document_property='B公司', sum_money=21, lecture=101}, DataRecord{id=33, tax_type='稿酬所得', document_property='B公司', sum_money=33, lecture=101}, DataRecord{id=45, tax_type='稿酬所得', document_property='B公司', sum_money=45, lecture=101}, DataRecord{id=57, tax_type='稿酬所得', document_property='B公司', sum_money=57, lecture=101}, DataRecord{id=69, tax_type='稿酬所得', document_property='B公司', sum_money=69, lecture=101}, DataRecord{id=81, tax_type='稿酬所得', document_property='B公司', sum_money=81, lecture=101}, DataRecord{id=93, tax_type='稿酬所得', document_property='B公司', sum_money=93, lecture=101}], 特许权使用费所得=[DataRecord{id=5, tax_type='特许权使用费所得', document_property='B公司', sum_money=5, lecture=101}, DataRecord{id=17, tax_type='特许权使用费所得', document_property='B公司', sum_money=17, lecture=101}, DataRecord{id=29, tax_type='特许权使用费所得', document_property='B公司', sum_money=29, lecture=101}, DataRecord{id=41, tax_type='特许权使用费所得', document_property='B公司', sum_money=41, lecture=101}, DataRecord{id=53, tax_type='特许权使用费所得', document_property='B公司', sum_money=53, lecture=101}, DataRecord{id=65, tax_type='特许权使用费所得', document_property='B公司', sum_money=65, lecture=101}, DataRecord{id=77, tax_type='特许权使用费所得', document_property='B公司', sum_money=77, lecture=101}, DataRecord{id=89, tax_type='特许权使用费所得', document_property='B公司', sum_money=89, lecture=101}], 劳务报酬所得=[DataRecord{id=1, tax_type='劳务报酬所得', document_property='B公司', sum_money=1, lecture=101}, DataRecord{id=13, tax_type='劳务报酬所得', document_property='B公司', sum_money=13, lecture=101}, DataRecord{id=25, tax_type='劳务报酬所得', document_property='B公司', sum_money=25, lecture=101}, DataRecord{id=37, tax_type='劳务报酬所得', document_property='B公司', sum_money=37, lecture=101}, DataRecord{id=49, tax_type='劳务报酬所得', document_property='B公司', sum_money=49, lecture=101}, DataRecord{id=61, tax_type='劳务报酬所得', document_property='B公司', sum_money=61, lecture=101}, DataRecord{id=73, tax_type='劳务报酬所得', document_property='B公司', sum_money=73, lecture=101}, DataRecord{id=85, tax_type='劳务报酬所得', document_property='B公司', sum_money=85, lecture=101}, DataRecord{id=97, tax_type='劳务报酬所得', document_property='B公司', sum_money=97, lecture=101}]}}, 102={A公司={稿酬所得=[DataRecord{id=6, tax_type='稿酬所得', document_property='A公司', sum_money=6, lecture=102}, DataRecord{id=18, tax_type='稿酬所得', document_property='A公司', sum_money=18, lecture=102}, DataRecord{id=30, tax_type='稿酬所得', document_property='A公司', sum_money=30, lecture=102}, DataRecord{id=42, tax_type='稿酬所得', document_property='A公司', sum_money=42, lecture=102}, DataRecord{id=54, tax_type='稿酬所得', document_property='A公司', sum_money=54, lecture=102}, DataRecord{id=66, tax_type='稿酬所得', document_property='A公司', sum_money=66, lecture=102}, DataRecord{id=78, tax_type='稿酬所得', document_property='A公司', sum_money=78, lecture=102}, DataRecord{id=90, tax_type='稿酬所得', document_property='A公司', sum_money=90, lecture=102}], 特许权使用费所得=[DataRecord{id=2, tax_type='特许权使用费所得', document_property='A公司', sum_money=2, lecture=102}, DataRecord{id=14, tax_type='特许权使用费所得', document_property='A公司', sum_money=14, lecture=102}, DataRecord{id=26, tax_type='特许权使用费所得', document_property='A公司', sum_money=26, lecture=102}, DataRecord{id=38, tax_type='特许权使用费所得', document_property='A公司', sum_money=38, lecture=102}, DataRecord{id=50, tax_type='特许权使用费所得', document_property='A公司', sum_money=50, lecture=102}, DataRecord{id=62, tax_type='特许权使用费所得', document_property='A公司', sum_money=62, lecture=102}, DataRecord{id=74, tax_type='特许权使用费所得', document_property='A公司', sum_money=74, lecture=102}, DataRecord{id=86, tax_type='特许权使用费所得', document_property='A公司', sum_money=86, lecture=102}, DataRecord{id=98, tax_type='特许权使用费所得', document_property='A公司', sum_money=98, lecture=102}], 劳务报酬所得=[DataRecord{id=10, tax_type='劳务报酬所得', document_property='A公司', sum_money=10, lecture=102}, DataRecord{id=22, tax_type='劳务报酬所得', document_property='A公司', sum_money=22, lecture=102}, DataRecord{id=34, tax_type='劳务报酬所得', document_property='A公司', sum_money=34, lecture=102}, DataRecord{id=46, tax_type='劳务报酬所得', document_property='A公司', sum_money=46, lecture=102}, DataRecord{id=58, tax_type='劳务报酬所得', document_property='A公司', sum_money=58, lecture=102}, DataRecord{id=70, tax_type='劳务报酬所得', document_property='A公司', sum_money=70, lecture=102}, DataRecord{id=82, tax_type='劳务报酬所得', document_property='A公司', sum_money=82, lecture=102}, DataRecord{id=94, tax_type='劳务报酬所得', document_property='A公司', sum_money=94, lecture=102}]}}, 103={B公司={稿酬所得=[DataRecord{id=3, tax_type='稿酬所得', document_property='B公司', sum_money=3, lecture=103}, DataRecord{id=15, tax_type='稿酬所得', document_property='B公司', sum_money=15, lecture=103}, DataRecord{id=27, tax_type='稿酬所得', document_property='B公司', sum_money=27, lecture=103}, DataRecord{id=39, tax_type='稿酬所得', document_property='B公司', sum_money=39, lecture=103}, DataRecord{id=51, tax_type='稿酬所得', document_property='B公司', sum_money=51, lecture=103}, DataRecord{id=63, tax_type='稿酬所得', document_property='B公司', sum_money=63, lecture=103}, DataRecord{id=75, tax_type='稿酬所得', document_property='B公司', sum_money=75, lecture=103}, DataRecord{id=87, tax_type='稿酬所得', document_property='B公司', sum_money=87, lecture=103}, DataRecord{id=99, tax_type='稿酬所得', document_property='B公司', sum_money=99, lecture=103}], 特许权使用费所得=[DataRecord{id=11, tax_type='特许权使用费所得', document_property='B公司', sum_money=11, lecture=103}, DataRecord{id=23, tax_type='特许权使用费所得', document_property='B公司', sum_money=23, lecture=103}, DataRecord{id=35, tax_type='特许权使用费所得', document_property='B公司', sum_money=35, lecture=103}, DataRecord{id=47, tax_type='特许权使用费所得', document_property='B公司', sum_money=47, lecture=103}, DataRecord{id=59, tax_type='特许权使用费所得', document_property='B公司', sum_money=59, lecture=103}, DataRecord{id=71, tax_type='特许权使用费所得', document_property='B公司', sum_money=71, lecture=103}, DataRecord{id=83, tax_type='特许权使用费所得', document_property='B公司', sum_money=83, lecture=103}, DataRecord{id=95, tax_type='特许权使用费所得', document_property='B公司', sum_money=95, lecture=103}], 劳务报酬所得=[DataRecord{id=7, tax_type='劳务报酬所得', document_property='B公司', sum_money=7, lecture=103}, DataRecord{id=19, tax_type='劳务报酬所得', document_property='B公司', sum_money=19, lecture=103}, DataRecord{id=31, tax_type='劳务报酬所得', document_property='B公司', sum_money=31, lecture=103}, DataRecord{id=43, tax_type='劳务报酬所得', document_property='B公司', sum_money=43, lecture=103}, DataRecord{id=55, tax_type='劳务报酬所得', document_property='B公司', sum_money=55, lecture=103}, DataRecord{id=67, tax_type='劳务报酬所得', document_property='B公司', sum_money=67, lecture=103}, DataRecord{id=79, tax_type='劳务报酬所得', document_property='B公司', sum_money=79, lecture=103}, DataRecord{id=91, tax_type='劳务报酬所得', document_property='B公司', sum_money=91, lecture=103}]}}}

(3)获取大map后,遍历改map,拿到sum_money进行加和,加入集合中。汇总Test类如下,可复制进行运行。

package com.jiankang.javacoretechnologythetenversion.dchapter10.v2;

/*
 *@create by jiankang
 *@date 2020/7/21 time 17:54
 * lambda 表达式研究
 */

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class Test {


    public static void main(String[] args) {
        List<DataRecord> results = new ArrayList<>();
        List<DataRecord> list = DataUtils.getDatas();
        //根据tax documentProperty ,lecture 分组
        Map<Integer, Map<String, Map<String, List<DataRecord>>>> bigMap = list.stream().filter(it ->
                it.getDocument_property() != null && it.getLecture() != null && it.getTax_type() != null
        ).collect(Collectors.groupingBy(DataRecord::getLecture, Collectors.groupingBy(DataRecord::getDocument_property, Collectors.groupingBy(DataRecord::getTax_type))));

        Set<Integer> lectures = bigMap.keySet();
        for (Integer lecture : lectures) {
            Map<String, Map<String, List<DataRecord>>> document_propertyMap = bigMap.get(lecture);
            Set<String> document_propertys = document_propertyMap.keySet();
            for (String document_property : document_propertys) {
                Map<String, List<DataRecord>> tax_typeMap = document_propertyMap.get(document_property);
                Set<String> tax_types = tax_typeMap.keySet();
                for (String tax_type : tax_types) {
                    List<DataRecord> dataRecords = tax_typeMap.get(tax_type);
                    if (dataRecords != null && dataRecords.size() > 0) {
                        DataRecord result = new DataRecord(null, null, null, new BigDecimal(0), null);
                        for (DataRecord dataRecord : dataRecords) {
                            result.setSum_money(result.getSum_money().add(dataRecord.getSum_money()));
                        }
                        result.setDocument_property(document_property);
                        result.setLecture(lecture);
                        result.setTax_type(tax_type);
                        results.add(result);
                    }
                }
            }
        }

        results.forEach(it -> System.out.println(it.toString()));
        System.out.println(results.size());
    }

}

(4)最后汇总后结果如下:

DataRecord{id=null, tax_type='稿酬所得', document_property='A公司', sum_money=432, lecture=100}
DataRecord{id=null, tax_type='特许权使用费所得', document_property='A公司', sum_money=400, lecture=100}
DataRecord{id=null, tax_type='劳务报酬所得', document_property='A公司', sum_money=368, lecture=100}
DataRecord{id=null, tax_type='稿酬所得', document_property='B公司', sum_money=408, lecture=101}
DataRecord{id=null, tax_type='特许权使用费所得', document_property='B公司', sum_money=376, lecture=101}
DataRecord{id=null, tax_type='劳务报酬所得', document_property='B公司', sum_money=441, lecture=101}
DataRecord{id=null, tax_type='稿酬所得', document_property='A公司', sum_money=384, lecture=102}
DataRecord{id=null, tax_type='特许权使用费所得', document_property='A公司', sum_money=450, lecture=102}
DataRecord{id=null, tax_type='劳务报酬所得', document_property='A公司', sum_money=416, lecture=102}
DataRecord{id=null, tax_type='稿酬所得', document_property='B公司', sum_money=459, lecture=103}
DataRecord{id=null, tax_type='特许权使用费所得', document_property='B公司', sum_money=424, lecture=103}
DataRecord{id=null, tax_type='劳务报酬所得', document_property='B公司', sum_money=392, lecture=103}

三、总结

       以上就是对lambda表达式的一些见解和经验,最后的业务场景实战算是比较复杂了,但是lambda表达对解决实际问题确实十分方便,逻辑更加清晰,希望可以帮到你,欢迎关注java基础笔记公众号,共勉。

猜你喜欢

转载自blog.csdn.net/jiankang66/article/details/100107363