java reduce 分组_java8新特性-reduce

reduce是用来执行聚合操作的

reduce方法有三个override的方法:

Optional reduce(BinaryOperator accumulator);

T reduce(T identity, BinaryOperator accumulator);

U reduce(U identity,BiFunction accumulator,BinaryOperator combiner);

1. 第一种方法

BinaryOperator接口,可以看到reduce方法接受一个函数,这个函数有两个参数,第一个参数是上次函数执行的返回值(也称为中间结果),第二个参数是stream中的元素,这个函数把这两个值相加,得到的和会被赋值给下次执行这个函数的第一个参数。要注意的是:第一次执行的时候第一个参数的值是Stream的第一个元素,第二个参数是Stream的第二个元素。这个方法返回值类型是Optional。

Optional accResult = Stream.of(1, 2, 3, 4)

.reduce((acc, item)->{

System.out.println("acc :" +acc);

acc+=item;

System.out.println("item:" +item);

System.out.println("acc+ :" +acc);

System.out.println("--------");returnacc;

});

System.out.println("accResult:" + accResult.get());

System.out.println("--------");//结果打印

--------acc :1item:2acc+ : 3

--------acc :3item:3acc+ : 6

--------acc :6item:4acc+ : 10

--------accResult:10

--------

2. 第二种方法

第二个变形,与第一种变形相同的是都会接受一个BinaryOperator函数接口,不同的是其会接受一个identity参数,用来指定Stream循环的初始值。如果Stream为空,就直接返回该值。另一方面,该方法不会返回Optional,因为该方法不会出现null。

int accResult = Stream.of(1, 2, 3, 4)

.reduce(0, (acc, item) ->{

System.out.println("acc :" +acc);

acc+=item;

System.out.println("item:" +item);

System.out.println("acc+ :" +acc);

System.out.println("--------");returnacc;

});

System.out.println("accResult:" +accResult);

System.out.println("--------");//结果打印

acc : 0item:1acc+ : 1

--------acc :1item:2acc+ : 3

--------acc :3item:3acc+ : 6

--------acc :6item:4acc+ : 10

--------accResult:10

--------

从打印结果可以看出,reduce前两种变形,因为接受参数不同,其执行的操作也有相应变化:

变形1,未定义初始值,从而第一次执行的时候第一个参数的值是Stream的第一个元素,第二个参数是Stream的第二个元素

变形2,定义了初始值,从而第一次执行的时候第一个参数的值是初始值,第二个参数是Stream的第一个元素

第三种方法

第一个参数返回实例u,传递你要返回的U类型对象的初始化实例u,第二个参数累加器accumulator,可以使用二元?表达式(即二元lambda表达式),声明你在u上累加你的数据来源t的逻辑,例如(u,t)->u.sum(t),此时lambda表达式的行参列表是返回实例u和遍历的集合元素t,函数体是在u上累加t,第三个参数组合器combiner,同样是二元?表达式,(u,t)->u。

因为reduce的变形的第一个参数类型是实际返回实例的数据类型,同时其为一个泛型也就是意味着该变形的可以返回任意类型的数据。从上面文档介绍的字面意思解读是第三个参数函数用来组合两个值,而这两个值必须与第二个函数参数相兼容,也就是说它们所得的结果是一样的。看到这里肯定有迷惑的地方,第三个参数到底是用来干嘛的?我们先看一段代码,为了便于了解其中的缘由,并没有使用Lambda表达式。

ArrayList accResult_ = Stream.of(1, 2, 3, 4)

.reduce(new ArrayList(),new BiFunction, Integer, ArrayList>() {

@Overridepublic ArrayList apply(ArrayListacc, Integer item) {

acc.add(item);

System.out.println("item:" +item);

System.out.println("acc+ :" +acc);

System.out.println("BiFunction");returnacc;

}

},new BinaryOperator>() {

@Overridepublic ArrayList apply(ArrayList acc, ArrayListitem) {

System.out.println("BinaryOperator");

acc.addAll(item);

System.out.println("item:" +item);

System.out.println("acc+ :" +acc);

System.out.println("--------");returnacc;

}

});

System.out.println("accResult_:" +accResult_);//结果打印

item: 1acc+ : [1]

BiFunction

item:2acc+ : [1, 2]

BiFunction

item:3acc+ : [1, 2, 3]

BiFunction

item:4acc+ : [1, 2, 3, 4]

BiFunction

accResult_: [1, 2, 3, 4]

accResult_:10

首先示例代码中,传递给第一个参数是ArrayList,在第二个函数参数中打印了“BiFunction”,而在第三个参数接口中打印了函数接口中打印了”BinaryOperator“.可是,看打印结果,只是打印了“BiFunction”,而没有打印”BinaryOperator“,说明第三个函数参数并没有执行。这里我们知道了该变形可以返回任意类型的数据。对于第三个函数参数,为什么没有执行,刚开始的时候也是没有看懂到底是啥意思呢,而且其参数必须为返回的数据类型?看了好几遍文档也是一头雾水。在 java8 reduce方法中的第三个参数combiner有什么作用?这里找到了答案,Stream是支持并发操作的,为了避免竞争,对于reduce线程都会有独立的result,combiner的作用在于合并每个线程的result得到最终结果。这也说明了了第三个函数参数的数据类型必须为返回数据类型了。

参考:https://blog.csdn.net/zhang89xiao/article/details/77164866?utm_medium=distribute.pc_relevant_download.none-task-blog-baidujs-2.nonecase&depth_1-utm_source=distribute.pc_relevant_download.none-task-blog-baidujs-2.nonecase

使用reduce实现分组统计

filterHistoryRankingList.stream().collect(Collectors.groupingBy(p -> p.getAdcode() + "_" + p.getLinksType() + "_" +p.getId()))

.forEach((String mapKey, List hisLinksIndicesRankingList) ->{

HisLinksIndicesRankingCalcBo hisLinksIndicesRankingCalcBo= new HisLinksIndicesRankingCalcBo(newHisLinksIndicesRanking());

hisLinksIndicesRankingList.stream().reduce(hisLinksIndicesRankingCalcBo, (u, t)-> u.calcRoad(t), (u, t) ->u);

resList.add(hisLinksIndicesRankingCalcBo.getHisLinksIndicesRanking());

});

数字累加

int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};//1st argument, init value = 0

int sum = Arrays.stream(numbers).reduce(0, (a, b) -> a +b);

System.out.println("sum :" + sum); //55

最大最小

int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};int max = Arrays.stream(numbers).reduce(0, (a, b) -> a > b ? a : b); //10

int max1 = Arrays.stream(numbers).reduce(0, Integer::max); //10

int min = Arrays.stream(numbers).reduce(0, (a, b) -> a < b ? a : b); //0

int min1 = Arrays.stream(numbers).reduce(0, Integer::min); //0

连接字符串

String[] strings = {"a", "b", "c", "d", "e"};//|a|b|c|d|e , the initial | join is not what we want

String reduce = Arrays.stream(strings).reduce("", (a, b) -> a + "|" +b);//a|b|c|d|e, filter the initial "" empty string

String reduce2 = Arrays.stream(strings).reduce("", (a, b) ->{if (!"".equals(a)) {return a + "|" +b;

}else{returnb;

}

});//a|b|c|d|e , better uses the Java 8 String.join :) (最好使用 Java 8 的 String.join)

String join = String.join("|", strings);

参考:https://www.cnblogs.com/gaohanghang/p/12390233.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值