用流收集数据

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));
8. 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是收集操作得到的对象(通常但并不一定是集合)的类型。

9. Collector 接口声明的方法
1. 建立新的结果容器: supplier 方法 supplier 方法必须返回一个结果为空的 Supplier ,也就是一个无参数函数,在调用时它会
创建一个空的累加器实例,供数据收集过程使用。
public Supplier<List<T>> supplier() { return () -> new ArrayList<T>();
} 2 请注意你也可以只传递一个构造函数引用:
public Supplier<List<T>> supplier(){
return ArrayList::new;
}
2. 将元素添加到结果容器: accumulator 方法
accumulator 方法会返回执行归约操作的函数
对于 ToListCollector ,这个函数仅仅会把当前项目添加至已经遍历过的项目的 列表:
public BiConsumer<List<T>, T> accumulator() { return (list, item) -> list.add(item);
}
方法引用:
public BiConsumer<List<T>, T> accumulator() { return List::add;
}
3. 对结果容器应用最终转换: finisher 方法
在遍历完流后, finisher 方法必须返回在累积过程的最后要调用的一个函数,以便将累加 器对象转换为整个集合操作的最终结果。
finisher 方法只需返回 identity 函数:
public Function<List<T>, List<T>> finisher() { return Function.identity();
}
4. 合并两个结果容器: combiner 方法
public BinaryOperator<List<T>> combiner() { return (list1, list2) -> {
list1.addAll(list2); return list1; }
}

猜你喜欢

转载自blog.csdn.net/LYX_WIN/article/details/80559234