目录
Java 中 Stream 流用来帮助处理集合,类似于数据库中的操作。
在 Stream 接口中,有一个抽象方法 collect,你会发现 collect 是一个归约操作(高级规约),就像 reduce 一样可以接受各种做法作为参数,将流中的元素累积成一个汇总结果。具体的做法可以通过Collector 接口来定义。// collect和reduce都是Stream接口中的汇总方法,collect方法接收一个Collector(收集器)作为参数
收集器(Collector)非常有用,Collector 接口中方法的实现决定了如何对流执行归约操作。//收集器用来定义收集器如何收集数据
一般来说,Collector 会对元素应用一个转换函数,并将结果累积在一个数据结构中,从而产生这一过程的最终输出。
Collectors 实用类提供了很多静态工厂方法,可以方便地创建常见收集器的实例,所以只要拿来用就可以了。最直接和最常用的收集器比如 toList、toSet、toMap 等静态方法。
1、归约和汇总
使用 Collectors 进行规约和汇总,比如统计汇总,查找最大值和最小值,拼接字符串等。
本节示例会使用到如下代码:
public class Dish {
private final String name;
private final boolean vegetarian;
private final int calories;
private final Type type;
public Dish(String name, boolean vegetarian, int calories, Type type) {
this.name = name;
this.vegetarian = vegetarian;
this.calories = calories;
this.type = type;
}
public String getName() {
return name;
}
public boolean isVegetarian() {
return vegetarian;
}
public int getCalories() {
return calories;
}
public Type getType() {
return type;
}
public enum Type {MEAT, FISH, OTHER}
@Override
public String toString() {
return name;
}
public static final List<Dish> menu = Arrays.asList(
new Dish("pork", false, 800, Type.MEAT),
new Dish("beef", false, 700, Type.MEAT),
new Dish("chicken", false, 400, Type.MEAT),
new Dish("french fries", true, 530, Type.OTHER),
new Dish("rice", true, 350, Type.OTHER),
new Dish("season fruit", true, 120, Type.OTHER),
new Dish("pizza", true, 550, Type.OTHER),
new Dish("prawns", false, 400, Type.FISH),
new Dish("salmon", false, 450, Type.FISH));
}
汇总操作:Collectors 类专门为汇总提供了一些工厂方法,用来满足各种类型的统计需要。
public static void main(String[] args) {
//1、计数
Long count0 = menu.stream().collect(Collectors.counting());
long count1 = menu.stream().count();
//2、汇总和
Integer summingInt = menu.stream().collect(Collectors.summingInt(Dish::getCalories));
//3、求平均数
Double averagingInt = menu.stream().collect(Collectors.averagingInt(Dish::getCalories));
//4、一次性求:计数量、总和、最大值、最小值、平均值
IntSummaryStatistics statistics = menu.stream().collect(Collectors.summarizingInt(Dish::getCalories));
//使用统计后的值
double average = statistics.getAverage();
long sum = statistics.getSum();
int max = statistics.getMax();
int min = statistics.getMin();
long count = statistics.getCount();
}
上述示例中,使用 summarizingInt 工方法返回的收集器功能很强大,通过一次 summarizing 操作你就可以统计到元素的个数,并得到总和、平均值、最大值和最小值。
查找流中的最大值和最小值:Collectors.maxBy 和 Collectors.minBy,来计算流中的最大或最小值。这两个收集器接收一个 Comparator 参数来比较流中的元素。
public static void main(String[] args) {
//比较器
Comparator<Dish> comparator = Comparator.comparing(Dish::getCalories);
//收集器
Optional<Dish> collect = menu.stream().collect(Collectors.maxBy(comparator));
}
连接字符串:joining 工厂方法返回的收集器会把对流中每一个对象应用 tostring 方法得到的所有字符串连接成一个字符串。如下所示:</