参考书籍《Java 8 实战》
// 实体类
public class Goods {
private String name;
private Integer price;
public static List<Goods> getGoods() {
List<Goods> goods = new ArrayList<>();
goods.add(new Goods("铅笔", 10));
goods.add(new Goods("面包", 20));
goods.add(new Goods("冰箱", 100));
goods.add(new Goods("水", 2));
goods.add(new Goods("口香糖", 8));
return goods;
}
}
将stream汇总为一个值
- 查找流中的最大最小值
// 求出价格最高的商品
Goods good = Test.goods.stream().collect(Collectors.maxBy(Comparator.comparing(Goods::getPrice))).get();
// 可以简化为
Goods good2 = Test.goods.stream().max(Comparator.comparing(Goods::getPrice)).get();
System.out.println(JSON.toJSONString(good));
System.out.println(JSON.toJSONString(good2));
// 价格最低的用min
-
元素汇总
例如对元素进行求和、求平均值等。
// 将价格求和
Integer sum = Test.goods.stream().collect(Collectors.summingInt(Goods::getPrice));
// 可以简化为
Integer sum2 = Test.goods.stream().mapToInt(Goods::getPrice).sum();
// 将价格求平均数
Double d1 = Test.goods.stream().collect(Collectors.averagingInt(Goods::getPrice));
System.out.println(sum);
System.out.println(sum2);
System.out.println(d1);
// 可以通过summarizingInt方法获取收集器,然后再收集里再去获取最大值、最小值、平均数等
IntSummaryStatistics statistics = Test.goods.stream().collect(Collectors.summarizingInt(Goods::getPrice));
System.out.println(statistics.getMax());
System.out.println(statistics.getAverage());
System.out.println(statistics.getCount());
System.out.println(statistics.getSum());
System.out.println(statistics.getMin());
-
拼接字符串
使用Collectors.joining()方法
// 将商品名称品接起来
String str = Test.goods.stream().map(Goods::getName).collect(Collectors.joining());
System.out.println(str);
// 如果需要间隔符
String str2 = Test.goods.stream().map(Goods::getName).collect(Collectors.joining(","));
System.out.println(str2);
元素分组
- 使用groupBy进行分组
// 根据类型进行分组
Map<String, List<Goods>> map = goods.stream().collect(Collectors.groupingBy(Goods::getType));
System.out.println(JSON.toJSONString(map));
// 如果想要更个性化一点,例如根据价格分组
Map<String, List<Goods>> map2 = goods.stream().collect(Collectors.groupingBy(a -> {
if (a.getPrice() > 1000) {
return "太贵了";
} else if ((a.getPrice() > 100)) {
return "可以接受";
} else {
return "挺便宜";
}
}));
System.out.println(JSON.toJSONString(map2));
- 多级分组
// 先根据类型分组,再根据价格分组
Map<String, Map<String, List<Goods>>> map = goods.stream().collect(Collectors.groupingBy(Goods::getType,
Collectors.groupingBy(b -> {
if (b.getPrice() > 4000) {
return "太贵了";
} else if ((b.getPrice() > 100)) {
return "可以接受";
} else {
return "挺便宜";
}
})
));
System.out.println(JSON.toJSONString(map));
- 按照分组收集数据
// 求出每个分类下的个数
Map<String, Long> count = goods.stream()
.collect(Collectors.groupingBy(Goods::getType, Collectors.counting()));
System.out.println(JSON.toJSONString(count));
// 求出每个分类下面最贵的商品
Map<String, Optional<Goods>> collect = goods.stream()
.collect(Collectors.groupingBy(Goods::getType,
maxBy(comparingInt(Goods::getPrice))));
// 使用collectingAndThen将 Optional<Goods>转为goods
// collectingAndThen 接受两个参数,要转换的收集器以及转换函数,并返回另一个收集器
Map<String, Goods> goodsMap = goods.stream()
.collect(Collectors.toMap(Goods::getType, Function.identity(), BinaryOperator.maxBy(comparingInt(Goods::getPrice))));
// 根据type分组,value是物品名称
// mapping接受两个参数,要一个是对流中的元素做变换,另一个则将变换的结果对象收集起来
Map<String, List<String>> nameList = goods.stream().collect(groupingBy(Goods::getType,
mapping(Goods::getName, toList())
));
System.out.println(JSON.toJSONString(nameList));
元素分区
分区和分组的概念及其类似。
// 将价格大于400的分为一组,小于400的分为一组
Map<Boolean, List<Goods>> maps =
goods.stream().collect(Collectors.partitioningBy(a -> a.getPrice() > 400));
System.out.println(maps.get(true));
System.out.println(maps.get(false));
// 当然根据groupingBy也可以实现
Map<Boolean, List<Goods>> maps2 = goods.stream().collect(Collectors.groupingBy(a -> {
if (a.getPrice() > 400) {
return true;
} else {
return false;
}
}));
System.out.println(maps2.get(true));
System.out.println(maps2.get(false));
// 分区里可以进行二级分组,先根据价格分区,然后再根据类型分组
Map<Boolean, Map<String, List<Goods>>> map3 = goods.stream().collect(Collectors.partitioningBy(a -> a.getPrice() > 400,
Collectors.groupingBy(Goods::getType)));