8.1.汇总

(1)Collectors.summingInt。它可接受一 个把对象映射为求和所需int的函数,并返回一个收集器;

(2)Collectors.averagingInt,连同对应的averagingLong和averagingDouble可以计算数值的平均数:

double avgCalories = menu.stream().collect(averagingInt(Dish::getCalories));

(3)summarizing操作你可以就数出菜单中元素的个数

(4)这个收集器会把所有这些信息收集到一个叫作IntSummaryStatistics的类里,它提供了 方便的取值(getter)方法来访问结果,相应的summarizingLong和summarizingDouble工厂方法有相关的LongSummary- Statistics和DoubleSummaryStatistics类型,适用于收集的属性是原始类型long或 double的情况

例如:

IntSummaryStatistics{count=9, sum=4300, min=120, average=477.777778, max=800}

2.连接字符串

joining工厂方法返回的收集器会把对流中每一个对象应用toString方法得到的所有字符

串连接成一个字符串

3.reducing方法创建的收集器来计算你菜单的总热量,如下所示:

int totalCalories = menu.stream().collect(reducing( 0, Dish::getCalories, (i, j) -> i + j));

它需要三个参数。

 第一个参数是归约操作的起始值,也是流中没有元素时的返回值,所以很显然对于数值

和而言0是一个合适的值。

  第二个参数就是你在6.2.2节中使用的函数,将菜肴转换成一个表示其所含热量的int。

  第三个参数是一个BinaryOperator,将两个项目累积成一个同类型的值。这里它就是 对两个int求和。

3.分组

Collectors.groupingBy方法传递了一个Function(以方法引用的形式),它提取了流中每 一道Dish的Dish.Type。我们把这个Function叫作分类函数,因为它用来把流中的元素分成不 同的组

4.多级分组

可以把一个内层groupingBy传递给外层groupingBy

例如,要数一数菜单中每类菜有多少个,可以传递counting收集器作为 groupingBy收集器的第二个参数:

Map<Dish.Type, Long> typesCount = menu.stream().collect( groupingBy(Dish::getType, counting()));

5.分区

分区是分组的特殊情况:由一个谓词(返回一个布尔值的函数)作为分类函数,它称分区函 数。分区函数返回一个布尔值,这意味着得到的分组Map的键类型是Boolean,于是它最多可以 分为两组——true是一组,false是一组

例如:

Map<Boolean,List<Dish> partitionedMenu =

menu.stream().collect(partitioningBy(Dish::isVegetarian));

List<Dish> vegetarianDishes = partitionedMenu.get(true);

7.Collectorsl类的静态工厂方法

工厂方法

返回类型

用于

toList

list<T>

把流中所有项目都收集到一个List

使用示例:List <Dish> dishes = menuStream.collect(toList());

toSet

Set<T>

把流中所有项目收集到一个Set,删除重复项

使用示例:Set<Dish> dishes = menuStream.collect(toSet());

toCollection

Collection<T>

把流中所有项目收集到给定的供应源创建的集合

使用示例:Collection<Dish> dishes = menuStream.collect(toCollection,ArrayList::new);

couting

Long

计算流中元素的个数

使用示例:long howmuchDishes = menuStream.collect(counting());

summingInt

Integer

对流中项目的一个整数属性求和

使用示例:int totalCalories = menuStream.collect(summingInt(Dish::getCalories));

averagingInt

Double

计算流中项目Integer属性的平均值

使用示例:Double avgCalories =menuStream.collect(averagingInt(Dish::getCalories));

summarizingInt

IntSummaryStartistics

收集关于流中项目Integer属性的统计值,例如最大、最小、总和与平均值

使用案例:IntSummaryStartistics menustartistics = menustream.collect(summarizingInt(Dish::getCalories));

joining

String

连接对流中每个项目调用toString方法所生成的字符串

使用示例:String shortMenu = menustream.map(Dish::getName).collect(joing(","));

maxBy

Optional<T>

一个包裹了流中按照给定比较器选出的最大元素Optional,或如果流为空则为Optional.empty()

使用示例:Optional<Dish> fattest = menuStream.collect(maxBy(comparingInt(Dish::getCalories)));

minBy

Optional<T>

一个包裹了流中按照给定比较器选出的最小元素Optional,或如果流为空则为Optional.empty()

使用示例:Optional<Dish> lighting = menuStream.collect(minBy(comparingInt(Dish::getCalories)));

reducing

归约操作产生类型

从一个作为累加器的初始值开始,利用BinaryOperator与流中的元素逐个结合,从而将流归约为单个值

使用示例:int totalCalories =menuStream.collect(reducing(0,Dish::getCalories,Integer::sum);

collectingAndThen

转换函数返回类型

包裹一个收集器,对比结果应用转换函数

使用示例:int howManyDishes = menuStream.collect(collectingAndThen(toList(),List::size));

groupingBy

Map<k,List<T>>

根据项目的一个属性的值对流中的项目作问组,并将属性值作 为结果 Map 的键

使用示例:Map<Dish.Type,List<Dish> dishesByType = menuStream.collect(groupingBy(Dish::getType));

partitioningBy

Map<Boolean,List<t>>

根据对流中每个项目应用谓词的结果来对项目进行分区

使用示例:Map<Boolean,List<Dish>> vegetarianDishes =menuStream.collect(partitioningBy(Dish::isVegetarian));

Collector 接口

public interface Collector<T, A, R> { Supplier<A> supplier(); BiConsumer<A, T> accumulator(); Function<A, R> finisher(); BinaryOperator<A> combiner(); Set<Characteristics> characteristics();

}

本列表适用以下定义。

 T 是流中要收集的项目的泛型。

 A 是累加器的类型,累加器是在收集过程中用于累积部分结果的对象。

 R是收集操作得到的对象(通常但并不一定是集合)的类型。

Collector 接口声明的方法

1. 建立新的结果容器: supplier 方法 supplier 方法必须返回一个结果为空的 Supplier ,也就是一个无参数函数,在调用时它会

创建一个空的累加器实例,供数据收集过程使用。

public Supplier<List<T>> supplier() { return () -> new ArrayList<T>();

} 2 请注意你也可以只传递一个构造函数引用:

public Supplier<List<T>> supplier(){

return ArrayList::new;

}

将元素添加到结果容器: accumulator 方法

accumulator 方法会返回执行归约操作的函数

对于 ToListCollector ,这个函数仅仅会把当前项目添加至已经遍历过的项目的 列表:

public BiConsumer<List<T>, T> accumulator() { return (list, item) -> list.add(item);

}

方法引用:

public BiConsumer<List<T>, T> accumulator() { return List::add;

}

对结果容器应用最终转换: finisher 方法

在遍历完流后, finisher 方法必须返回在累积过程的最后要调用的一个函数,以便将累加 器对象转换为整个集合操作的最终结果。

finisher 方法只需返回 identity 函数:

public Function<List<T>, List<T>> finisher() { return Function.identity();

}

合并两个结果容器: combiner 方法

public BinaryOperator<List<T>> combiner() { return (list1, list2) -> {

list1.addAll(list2); return list1; }

}