Stream Collectors - reducing

news/2024/7/5 7:32:59 标签: java

public static <T> Collector<T,​?,​Optional<T>> reducing​(BinaryOperator<T> op)

不能看方法名理解其作用,入参是一个二目运算函数参数,作用比较广泛。

处理流程简单描述:

第一步;a,b两个参数先分别赋值集合中的第一个和第二个元素,经过计算的结果赋值给a。

第二步;取集合中第三个元素赋值给b,然后再对a,b两个参数进行计算,计算结果还是赋值给a。

第三步;重复第二步,直到遍历完全部集合元素。

第四步;把最终结果放到Optional中返回。

看一个例子:

void test34() {

        List<Integer> list = List.of(2,5,8,9,4,20,11,43,55);

        Optional<Integer> sum = list.stream().collect(Collectors.reducing((a,b) -> a+b));

        System.out.println(sum.get());

    }

运行结果:157

最后再强调一下,这个方法作用非常广泛功能非常强大。特别是配合groupingBy或partitioningBy使用简直是非常的好用。

看个例子:

void test35() {

        List<User> userList = List.of((new User("mail1","adr1")),(new User("mail2","a2")),(new User("mail2","adr3")),(new User("mail1","adrr4")));

        Map<String,Optional<User>> map = userList.stream().collect(Collectors.groupingBy(a -> a.getEmail(), Collectors.reducing((b,c) -> b.getAddr().length()<c.getAddr().length()?b:c)));

        map.forEach((a,b) -> System.out.println(a+" : "+b.get().getAddr()));

    }

运行结果:

mail2 : a2

mail1 : adr1

简单说一下代码的作用,就是以mail字段分组,分组结果取addr字段中字符串长度最小的User。

这个需求要是搁在java8之前去实现可以说绝对不可能一行代码就能解决,java8之前实现的思路基本上是这样,先对集合进行遍历,分别把相同mail的user放在同一个数组当中,再以mail为key,存放相同mail的user数组为value放到map当中,然后再遍历map中的value取出addr长度最小user保存到Optional中,最后以mail为key,最后一步得到的Optional为value放到map中返回。

 

public static <T> Collector<T,​?,​T> reducing​(T identity, BinaryOperator<T> op)

在上个例子函数参数的两个入参初始化的时候是取集合中头两个元素,然后把计算结果赋值给第一个参数,第二个参数继续取集合中第三个元素然后使用这两个参数进行计算,以此类推完成整个集合元素的计算。在这个两个参数的reducing方法中比上个方法多了一个identity参数,这个参数的作用就是用来初始化第二个函数参数中的第一个入参的。计算流程简述如下:第一次计算中两个入参的第一个入参赋值identity值,第二个入参取集合中第一元素,然后进行计算,计算结果赋值第一个参数,第二个参数继续取集合中的第二个元素进行计算,以此类推,完成整个集合元素的计算。

看一个例子:

void test36() {

        List<Integer> list = List.of(2,5,8,9,4,20,11,43,55);

        Integer sum2 = list.stream().collect(Collectors.reducing(1, Integer::sum));

        System.out.println(sum2);

    }

运行结果是:158

 

对比一下上一个reducing方法,其差异就是二目运算函数中的两个入参第一次计算的时候初始赋值方法不一样,后面计算的处理流程一致。

// reducing 单参数和两个参数方法的区别

    void test37() {

        List<Integer> list = List.of(2,5,8,9,4,20,11,43,55);

        // 模拟单参数reducing,其中 a第一次取的是list中的第一个元素,之后a取的都是a,b计算结果

        int a=0,b=0;

        boolean c = true;

        for(int i: list) {

            if(c) {a = i; c = false;}

            else b = i;

            a += b;

        }

        System.out.println(a); // 157

       

        // 模拟2参数reducing, 其中a是在循环之前赋值,在reduceing中就是把第一个参数值赋给a,之后a都是取值a,b计算结果。

        a=1;

        for(int i: list) {

            b = i;

            a += b;

        }

        System.out.println(a); // 158

    }

 

public static <T,​U> Collector<T,​?,​U> reducing​(U identity, Function<? super T,​? extends U> mapper, BinaryOperator<U> op)

三个参数的reducing,结合前面两个方法可以很容易理解这个方法的作用,其实这个方法和两个参数方法作用差不多,多了的第二个参数作用就是我们可以对取出的元素在使用第三个参数函数进行计算前先进行处理。两个参数的reducing就只能把从集合中取出的元素原原本本的放到第三个参数函数中进行计算。

看一个示例:

      

void test38() {

        List<Integer> list = List.of(2,5,8,9,4,20,11,43,55);

        Integer sum2 = list.stream().collect(Collectors.reducing(0, a->1, Integer::sum));

        System.out.println(sum2);

    }

运行结果:9

这里例子其实就是利用reducing方法求集合中的元素数量。如果把第二个参数修改为 a->a,那其作用还是求和,运行结果157

在看一个例子:

void test39() {

        List<User> userList = List.of((new User("mail1","adr1")),(new User("mail2","a2")),(new User("mail2","adr3")),(new User("mail1","adrr4")));

        String str = userList.stream().collect(Collectors.reducing("adr: ", a->a.getAddr(), (c,d) -> c+d+","));

        System.out.println(str);

    }

运行结果: adr: adr1,a2,adr3,adrr4,

代码的作用就是把集合中所有的user地址列出来。可以看到我们使用第二个参数先从user对象中取出地址,然后再放到第三个参数函数中计算,当然我们使用两个函数的reducing也能做到,只是取user中地址的操作就必须放到第三个参数函数里进行了。


http://www.niftyadmin.cn/n/928504.html

相关文章

这才是Tomcat内存配置的正确姿势

1.背景 虽然阅读了各大牛的博客或文章,但并没有找到特别全面的关于JVM内存分配方法的文章,很多都是复制黏贴 为了严谨,本文特别备注只介绍基于HotSpot VM虚拟机,并且基于JDK1.7的内存分配情况,有关GC的说法也是基于CMS的concurrent collection(而非G1),防止大牛拍砖. 目前主流的…

拥抱PostgreSQL,红帽再表态:SSPL的MongoDB坚决不用

2019年1月&#xff0c;红帽在最新的RHEL 8.0 Beta Release Note 中明确表示因为 MongoDB 使用了 SSPL 协议&#xff0c;所以将不会在 8.0 系统中提供该数据库。 2019年2月12日&#xff0c;红帽官方发博称&#xff0c;Red Hat Satellite将在后端标准化PostgreSQL&#xff0c;并且…

Stream Collectors - summarizingInt

public static <T> Collector<T,​?,​IntSummaryStatistics> summarizingInt​(ToIntFunction<? super T> mapper) public static <T> Collector<T,​?,​LongSummaryStatistics> summarizingLong​(ToLongFunction<? super T> mapp…

1_npctele

1_npctele 其他同1_itemtele slot       排序字段(传送NPC中的显示根据这个来排序 也就是 数值越小的越在前)creature    传送员id (这里指定ID可以设置多个传送员)parentmenuidicongossipmapposition_xposition_yposition_zposition_oactionvendoridreqtypereqva…

Go语言的通道(2)-缓冲通道

有缓冲的通道相比于无缓冲通道&#xff0c;多了一个缓存的功能&#xff0c;如下图描述的一样&#xff1a; 从图上可以明显看到和无缓冲通道的区别&#xff0c;无缓冲必须两个Goroutine都进入通道才能进行数据的交换&#xff0c;这个不用&#xff0c;如果数据有&#xff0c;直接…

Stream Collectors - summingInt

public static <T> Collector<T,​?,​Integer> summingInt​(ToIntFunction<? super T> mapper) public static <T> Collector<T,​?,​Long> summingLong​(ToLongFunction<? super T> mapper) public static <T> Collector…

为什么要应用编排,应用编排能做什么?

随着服务数量的增多&#xff0c;对服务配置的管理也提出了更高的要求。如何去管理诸多服务&#xff0c;不同环境中存在差异部分以及在系统运维阶段需要灵活变更的部分&#xff0c;这些都是服务配置管理中需要解决的问题。通过应用编排产生的编排模版保存了每个服务本身具体的部…

Stream Collectors - toCollection

public static <T,​C extends Collection<T>> Collector<T,​?,​C> toCollection​(Supplier<C> collectionFactory) 简述一下就是把集合中的元素转换成参数指定的集合类型进行保存。 看个例子&#xff1a; void test42() {List<Integer> …