归约与汇总
- 归约(reduce):将Stream流中元素转换成一个值
- 汇总(collect):将Stream流中元素转换成一个容器(集合类等的容易)
归约
将Stream流中元素转换成一个值,只返回一个值!!!
1 2 3 4 5 6 7 8 9 10
| Stream<Integer> integerStream = Lists.newArrayList(1, 2, 3).stream();
integerStream.mapToInt(Integer::intValue).max();
integerStream.mapToInt(Integer::intValue).min();
integerStream.mapToInt(Integer::intValue).sum();
|
归约操作理解
例如:一个Stream流进行累加

reduce接口参数
以reduce最复杂的接口参数为例
1 2 3 4 5 6 7 8 9 10 11
|
<U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);
|
结合图查看接口做了什么(分治思想)

实战案例:自定义归约
根据一批订单信息,计算平均商品价格
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| package com.stream.shopping;
import cn.hutool.json.JSONUtil; import lombok.AllArgsConstructor; import lombok.Data; import org.junit.jupiter.api.Test;
import java.util.ArrayList; import java.util.List;
public class ReduceAndCollectTest {
@Test void reduceTest() {
@Data @AllArgsConstructor class Order {
private Integer id;
private Integer productCount;
private Double totalAmount; } List<Order> list = new ArrayList<>(); list.add(new Order(1, 2, 25.12)); list.add(new Order(2, 5, 257.23)); list.add(new Order(3, 3, 25512.12));
Order order = list.stream() .parallel() .reduce( new Order(0, 0, 0.0), (Order order1, Order order2) -> { System.out.println("执行计算逻辑方法"); int productCount = order2.getProductCount() + order1.getProductCount(); double totalAmount = order1.getTotalAmount() + order2.getTotalAmount(); return new Order(0, productCount, totalAmount); }, (Order order1, Order order2) -> { System.out.println("执行合并方法"); int productCount = order1.getProductCount() + order2.getProductCount(); double totalAmount = order1.getTotalAmount() + order2.getTotalAmount(); return new Order(0, productCount, totalAmount); } ); System.out.println(JSONUtil.parse(order)); } }
|
执行结果

汇总
将Stream流中元素转换成一个容器
1 2 3 4 5 6 7 8 9 10
| Stream<Integer> integerStream = Lists.newArrayList(1, 2, 3).stream();
List<Integer> list = integerStream.collect(Collectors.toList());
Map<Boolean, List<Integer>> partitions = integerStream.collect(Collectors.partitioningBy(item -> item % 2 == 0));
Map<Boolean, List<Integer>> groups = integerStream.collect(Collectors.groupingBy(item -> item));
|
collect接口参数
1 2 3 4 5 6 7 8 9 10 11
|
<R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner);
|
实战案例:自定义收集
根据一批订单信息,计算每个用户的平均商品价格
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| @Test void collectTest() {
@Data @AllArgsConstructor class Order {
private Integer id;
private String account;
private Integer productCount;
private Double totalAmount; }
List<Order> list = new ArrayList<>(); list.add(new Order(1, "zhangsan", 2, 25.12)); list.add(new Order(2, "zhangsan", 5, 257.23)); list.add(new Order(3, "lisi", 3, 25512.12));
HashMap<String, Order> orderHashMap = list.stream() .parallel() .collect( () -> { System.out.println("执行初始化容器操作"); return new HashMap<String, Order>(); }, (HashMap<String, Order> map, Order newOrder) -> { System.out.println("执行新元素添加到容器操作"); String account = newOrder.getAccount(); if (map.containsKey(account)) { Order order = map.get(account); order.setProductCount(newOrder.getProductCount() + order.getProductCount()); order.setTotalAmount(newOrder.getTotalAmount() + order.getTotalAmount()); } else { map.put(account, newOrder); } }, (HashMap<String, Order> map1, HashMap<String, Order> map2) -> { System.out.println("执行并行结果合并操作"); map2.forEach((key, value) -> { map1.merge(key, value, (order1, order2) -> { return new Order(0, key, order1.getProductCount() + order2.getProductCount(), order1.getTotalAmount() + order2.getTotalAmount()); }); }); } ); System.out.println(JSONUtil.parse(orderHashMap)); } }
|
执行结果

问题:多次初始化容器map会不会存在内容泄露风险
解答:方法里面的局部变量,方法执行完,没有外部引用了,自然会被标记为可回收,等待GC回收