目录
一、前言
1.1 收集器
1.2 预约义收集器
Collectors类为咱们提供的收集器,次要蕴含三大性能:
二、深刻
2.1 规约和汇总
统计元素数量
查找流中的最大值和最小值
汇总
连贯字符串
2.2 分组
一、前言
1.1 收集器
收集器的接口是java.util.stream.Collector,咱们只须要调用流的collect办法并传递给一个Collector接口的一个实现(也就是给Stream中元素做汇总的办法),就能够了。例如java.util.stream.Collectors类的toList()办法,该办法就会返回一个按程序给每个元素生成一个列表的Collector接口的实现。
收集器十分有用,因为它能够简介而灵便地定义collect用来生成后果汇合的规范。更具体地说,对流调用collect办法将对流中的元素触发一个规约操作(由Collector来参数化)。
1.2 预约义收集器
JDK为咱们提供了java.util.stream.Collectors类,其为咱们提供了很多动态工厂办法,能够不便地创立常见的收集器实例,而咱们只有拿来用就能够了。最间接和最罕用的收集器是toList静态方法,它会把流中所有的元素收集到一个List中。
Collectors类为咱们提供的收集器,次要蕴含三大性能:
将流元素规约和汇总为一个值
元素分组
元素分区
留神:因为其为咱们提供的都是静态方法,咱们能够通过动态导入的形式简化代码的书写。
二、深刻
2.1 规约和汇总
统计元素数量
Collectors为咱们提供了counting办法,为咱们提供了统计元素数量的收集器。实例:
long howManyDishes = menu.stream().collect(Collectors.counting());
下面的示例是利用预约义收集器实现的,其实Stream接口定义了count办法,因而咱们也能够间接调用Stream提供的预定义方法来实现,如下:
long howManyDishes = menu.stream().count();
性能一样用哪个才好呢?其实如果你的需要只是统计流中元素的数量的时候,二者皆可。最大的区别在于count()是一个终端操作,而counting返回的是一个收集器,其能够和其它收集器联结应用。
查找流中的最大值和最小值
Collectors为咱们提供了maxBy办法和mixBy办法,为咱们提供了计算流中的最大或最小值的收集器。实例:
Comparator<Dish> dishCaloriesComparator = Comparator.comparingInt(Dish::getCalories); Optional<Dish> mostCalorieDish = menu.stream().collect(maxBy(dishCaloriesComparator));
汇总
求和
Collectors类专门为汇总提供了一个工厂办法: Collectors.summingInt。它可承受一个把对象映射为求和所需int的函数,并返回一个收集器;该收集器在传递给一般的collect办法后即执行咱们须要的汇总操作。
类Collectors.summingLong和Collectors.summingDouble办法的作用齐全一样,能够用于求和字段为long或double的状况。
求出菜单列表的总热量的示例:
int totalCalories = menu.stream().collect(summingInt(Dish::getCalories));
下面代码的收集过程下图所示。在遍历流时,会把每一道菜都映射为其热量,而后把这个数字累加到一个累加器(这里的初始值0)。
平均值
Collectors类的averagingInt、averagingLong 和 averagingDouble 能够为咱们生成计算数值的平均数的收集器:
double avgCalories = menu.stream().collect(averagingInt(Dish::getCalories));
Collectors类为咱们提供了summarizingInt工厂办法,其返回的收集器能够一次性统计出总数、总和、平均值、最大值和最小值。
例如,通过一次summarizing操作你能够就数出菜单中元素的个数,并失去菜肴热量总和、平均值、最大值和最小值:
IntSummaryStatistics menuStatistics = menu.stream().collect(summarizingInt(Dish::getCalories));
这个收集器会把所有这些信息收集到一个叫作IntSummaryStatistics的类里,它提供了不便的取值办法来拜访后果。打印menuStatisticobject会失去以下输入:
IntSummaryStatistics{count=9, sum=4300, min=120, average=477.777778, max=800}
同样,相应的summarizingLong和summarizingDouble工厂办法有相干的LongSummaryStatistics 和DoubleSummaryStatistics 类 型 , 实用于收集的属性是原始类型 long 或 double 的状况。
连贯字符串
Collectors类为咱们提供的joining工厂办法返回的收集器会把对流中每一个对象利用toString办法失去的所有字符串连接成一个字符串。
这意味着你把菜单中所有菜肴的名称连接起来,如下所示:
String shortMenu = menu.stream().map(Dish::getName).collect(joining());
留神: joining在外部应用了StringBuilder来把生成的字符串一一追加起来。
此外joining工厂办法有一个重载版本能够承受元素之间的分界符,这样你就能够失去一个逗号分隔的菜肴名称列表:
String shortMenu = menu.stream().map(Dish::getName).collect(joining(", "));
狭义的规约汇总
后面所提及的收集器都是一个能够用reducing工厂办法定义的规约过程的非凡状况而已。Collectors.reducing工厂办法是所有这些非凡状况的一般化。
public static <T,U> Collector<T,?,U> reducing(U identity, Function<? super T,? extends U> mapper, BinaryOperator<U> op)
参数解析:
第一个参数时规约操作的起始值,也是流中没有元素时的返回值。
第二个参数是Function,将做肯定的转换操作。
第三个参数BinaryOperator,将两个我的项目累积成一个同类型的值。
咱们将下面的示例转换一下:
Comparator<Dish> dishCaloriesComparator = Comparator.comparingInt(Dish::getCalories); Optional<Dish> mostCalorieDish = menu.stream().collect(maxBy(dishCaloriesComparator)); // 转换 Optional<Dish> mostCalorieDish = menu.stream().collect(reducing( (d1,d2) -> d1.getCalories() > d1.getCalories() ? d1 : d2));
下面转换示例中,咱们应用的是一个单参数的reducing工厂办法创立的收集器,其能够看做是三个参数办法的非凡状况,它把流中的第一个我的项目作为终点,把恒等函数(即一个函数仅仅是返回其输出参数)作为一个转换函数。
2.2 分组
一个常见的数据库操作是依据一个或多个属性对汇合中的我的项目进行分组。
假如你要把菜单中的菜依照类型进行分类,有肉的放一组,有鱼的放一组,其余的都放另一组。用Collectors.groupingBy工厂办法返回的收集器就能够轻松地实现这项工作,如下所示:
Map<Dish.Type, List<Dish>> dishesByType = menu.stream().collect(groupingBy(Dish::getType));
这里,你给groupingBy办法传递了一个Function(以办法援用的模式),它提取了流中每一道Dish的Dish.Type。咱们把这个Function叫作分类函数,因为它用来把流中的元素分成不同的组。如下图所示,分组操作的后果是一个Map,把分组函数返回的值作为映射的键,把流中所有具备这个分类值的我的项目的列表作为对应的映射值。在菜单分类的例子中,键就是菜的类型,值就是蕴含所有对应类型的菜肴的列表。
非凡利用示例:
public enum CaloricLevel{DIET,NORMAL,FAT} Map<CaloricLevel, List<Dish>> dishesByCaloricLevel = menu.stream().collect(groupingBy(dish -> { if (dish.getCalories() <= 400) return CaloricLevel.DIET; else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL; else return CaloricLevel.FAT; }));
以上为集体教训,心愿能给大家一个参考