• Collectors.collectingAndThen()


    Collectors.collectingAndThen()

    Java 8 流的新类 java.util.stream.Collectors 实现了 java.util.stream.Collector 接口,同时又提供了大量的方法对流 ( stream ) 的元素执行 map and reduce 操作,或者统计操作。

    Collectors.collectingAndThen() 函数应该最像 map and reduce 了,它可接受两个参数,第一个参数用于 reduce操作,而第二参数用于 map操作。

    也就是,先把流中的所有元素传递给第一个参数,然后把生成的集合传递给第二个参数来处理。

    例如下面的代码

    1. [1,2,3,4] 这个集合传递给 v -> v * 2 lambda表达式,计算得出结果为[2,4,6,8]
    2. 然后再把 [2,4,6,8]传递给 Collectors.averagingLong 表达式,计算得出 5.0
    3. 然后传递给 s -> s * s lambda表达式,计算得到结果为 25.0

    collectingAndThenExample测试

    @Test
    public void collectingAndThenExample() {
        List<Integer> list = Arrays.asList(1, 2, 3, 4);
        Double result = list.stream().collect(Collectors.collectingAndThen(Collectors.averagingLong(v -> {
                    System.out.println("v--" + v + "--> " + v * 2);
                    return v * 2;
                }),
                s -> {
                    System.out.println("s--" + s + "--> " + s * s);
                    return s * s;
                }));
        System.out.println(result);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    collectingAndThenExample结果

    v--1--> 2
    v--2--> 4
    v--3--> 6
    v--4--> 8
    s--5.0--> 25.0
    25.0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    一点唠叨:

    • 相对于Collectors.averagingDouble()来说,方法体只执行一次。
    • 相对于Collectors.averagingDouble()来说,方法体做出了优化
    • 相对于Collectors.averagingDouble()来说,这个没有坑
    • ……
    • 为什么这么提Collectors.averagingDouble(),因为Collectors.averagingDouble()有坑,有坑,有坑


    Collectors.collectingAndThen 去重

    • Adapts a Collector to perform an additional finishing transformation
    • 对结果集收集的结果再用function函数进行处理,第一个参数是Collector,可以使用Collectors里面的各种工具类
    public static <T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream, Function<R,RR> finisher)
    
    • 1

    应用:根据list中对象某属性进行去重

    List<Student> studentList = new ArrayList<>();
    studentList.add(new Student("111", 132774, 12, "1"));
    studentList.add(new Student("123", 13556, 15, "1"));
    studentList.add(new Student("1146", 13165142, 16, "1"));
    studentList.add(new Student("111", 136542, 14, "2"));
    studentList.add(new Student("141321", 5641542, 15, "2"));
    studentList.add(new Student("1454135", 2222542, 15, "2"));
    
    List<Student> collect = studentList.stream().collect(
    		Collectors.collectingAndThen(
    		        Collectors.toCollection( 
    		                () -> new TreeSet<>(Comparator.comparing(Student::getStuName))),
    		        ArrayList::new));
    
    System.out.println(collect.size());
    
    // 等效处理   此处在treeSet构造方法中传入比较器 可以自定义比较器传入
    TreeSet<Student> treeSet = new TreeSet<>(Comparator.comparing(Student::getStuName));
    treeSet.addAll(studentList);
    List<Student> treeCollect = new ArrayList<>(treeSet);
    
    System.out.println(treeCollect.size());
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    output

    Student{stuName='111', stuId=132774, stuAge=12, classNum='1'}
    Student{stuName='1146', stuId=13165142, stuAge=16, classNum='1'}
    Student{stuName='123', stuId=13556, stuAge=15, classNum='1'}
    Student{stuName='141321', stuId=5641542, stuAge=15, classNum='2'}
    Student{stuName='1454135', stuId=2222542, stuAge=15, classNum='2'}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 第一种方法的finisher调用的是ArrayList(Collection c),所以就是把Collector downstream的结果再给到Function finisher去处理,用toCollection收集结果
    • 第二种用treeSet就是用比较器来进行排序去重,如果compareTo返回0,说明是重复的,返回的是自己的某个属性和另一个对象的某个属性的差值,如果是负数,则往前面排,如果是正数,往后面排。在set放元素时,是一个循环比较的过程,一旦有一个相等,就不再比较。
    • ComparTo()方法是一个比较方法,比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。默认为零系统认为都是同一个对象,所以只存入一个,因为Set集合的无序、唯一性

    Stream分组groupBy后取单一字段值、取列表第一个值方式

    取某字段成为列表

    Map<String, List<String>> ruleMap1 = ruleList.stream().
                    .collect(Collectors.groupingBy(Rule::getId,
                            Collectors.mapping(Rule::getRuleName, Collectors.toList())));
    
    • 1
    • 2
    • 3

    取列表中第一个值

            Map<String, Rule> ruleMap = ruleList.stream().
                    .collect(Collectors.groupingBy(Rule::getId,
                            Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0))));
    
    • 1
    • 2
    • 3
  • 相关阅读:
    windows server 2016 中users组用户权限实探
    《下一代互联网(IPv6)搭建与运维》1+X证书
    .NET Core 使用Swagger给控制器分组
    Python学习----Day07
    uniapp云打包app使用sqlite实现本地缓存,以及云打包sqlite不生效踩坑记录
    【学习笔记】用线段树维护区间计数问题
    会议OA系统07(所有会议,待开会议)
    【Android 从入门到出门】第一章:Android开发技能入门指南
    MITSUBISHI A1SJ51T64电源单元
    使用RocketMQ 实现基于标签过滤的消息队列生产和消费
  • 原文地址:https://blog.csdn.net/qq_43842093/article/details/128058117