Java8学习五 Stream之使用流收集数据
文章目录
具体地说,流收集器是对流调用collect方法将对流中的元素触发一个归约操作( 由Collector来参数化)。
归约和汇总
计数counting
|
|
最大值和最小值
最大值
maxBy
1 2
menu.stream().collect(Collectors.maxBy(Comparator .comparingInt(Dish::getCalories)));
1 2 3 4
//使用reduceing实现相同功能 menu.stream().collect(Collectors .reducing((Dish d1, Dish d2) -> d1.getCalories() > d2.getCalories() ? d1 : d2));
最小值
minBy
1 2 3
menu.stream().collect(Collectors.minBy( Comparator.comparingInt(Dish::getCalories) ));
汇总
summingInt
1
menu.stream().collect(Collectors.summingInt(Dish::getCalories)
1 2 3 4 5 6 7
//使用reduceing实现相同功能 //方式一 menu.stream().collect(Collectors.reducing(0, Dish::getCalories, (a, b) -> a + b)); // 方式二 menu.stream().collect((Collectors.reducing(0, Dish:: getCalories, Integer:: sum)));
summarizingInt
得到总和、平均值、最大值、最小值1
menu.stream().collect(Collectors.summarizingInt(Dish::getCalories));
输出结果为:
IntSummaryStatistics{count=9, sum=4200, min=120, average=466.666667, max=800}
相应的
summarizingLong
和summarizingDouble
工厂方法对应相关的LongSummaryStatistics
和DoubleSummaryStatistics
类型。
连接字符串
|
|
joining 内部使用StringBuilder连接字符串。
Collectors.reducing
Collectors.reducing
工厂方法是所有归约汇总方法的一般化,即上述所有功能都可通过reducing
实现。
reducing
方法接收三个参数
- 第一个参数,归约操作的起始值
- 第二个参数,
Function<T, R>
类型- 第三个参数,
BinaryOperator<U>
类型
分组
简单分组
|
|
|
|
多级分组
根据类型和卡路里分组
1 2 3 4 5 6 7 8 9 10 11 12 13
Map<Dish.Type, Map<CaloricLevel, List<Dish>>> dishByTypeCaloricLevel = menu.stream().collect( Collectors.groupingBy(Dish::getType, Collectors.groupingBy(dish -> { if (dish.getCalories() <= 400 ){ return CaloricLevel.DIET; }else if (dish.getCalories() <= 700) { return CaloricLevel.NORMAL; }else { return CaloricLevel.FAT; } }) ) );
按类型分组并计算每组数量
1 2
Map<Dish.Type, Long> typesCount = menu.stream(). collect(Collectors.groupingBy(Dish::getType, Collectors.counting()));
按类型分组并查找卡路里最大的
1 2 3 4 5 6 7 8
//返回Optional类型 Map<Dish.Type, Optional<Dish>> typesMostCaloriesOP = menu.stream() .collect( Collectors.groupingBy(Dish::getType, Collectors.maxBy( Comparator.comparingInt(Dish:: getCalories) ) ) );
把收集器结果转换为另一种类型:
Collectors.collectingAndThen
|
|
按类型分组并计算热量总和
1 2 3
Map<Dish.Type, Integer> typesCaloriesCount = menu.stream(). collect(Collectors.groupingBy(Dish::getType, Collectors.summingInt(Dish::getCalories)));
按类型分组并映射为卡路里级别
Collectors.mapping
1 2 3 4 5 6 7 8 9 10 11
Map<Dish.Type, Set<CaloricLevel>> caloricLevelByType = menu.stream(). collect(Collectors.groupingBy(Dish::getType, Collectors.mapping((Dish dish) -> { if (dish.getCalories() <= 400 ){ return CaloricLevel.DIET; }else if (dish.getCalories() <= 700) { return CaloricLevel.NORMAL; }else { return CaloricLevel.FAT; } }, Collectors.toCollection(HashSet::new)/*Collectors.toSet()*/)));
分区
由一个谓词(返回一个布尔值的函数)作为分类函数,称为分区函数。意味着分组Map的键类型为Boolean,最多可分两组——true一组,false一组。
按照是否是素菜分区
1 2
Map<Boolean, List<Dish>> partitionedMenu = menu.stream(). collect(Collectors.partitioningBy(Dish:: isVegetarian));
按照是否是素菜分区并按类型分组
1 2 3
Map<Boolean, Map<Dish.Type, List<Dish>>> partitionedMenuGroupByType = menu.stream().collect( Collectors.partitioningBy(Dish::isVegetarian, Collectors.groupingBy(Dish::getType))
数字按质数和非质数分区
1 2 3 4 5 6 7 8 9 10 11 12
public static boolean isPrime(int candidate){ int candidateRoot = (int) Math.sqrt((double) candidate); return IntStream.rangeClosed(2, candidateRoot) .noneMatch(i -> candidate % i == 0); } public static Map<Boolean, List<Integer>> partitionPrimes(int n){ return IntStream.rangeClosed(2, n) .boxed() .collect(Collectors.partitioningBy(candidate -> isPrime(candidate))); } partitionPrimes(20)
本文为学习记录,因能力有限,如有错误请赐教……如需转载,请注明出处!
文章作者 binbin wen
上次更新 2018-09-06