Java8中提供的收集器
- 作用:Collector(收集器会对元素引用一个转换函数,并且将结果累计在一个数据结构中,如toList,从而产生一个最终输出)
Java中的预定义收集器(预定义收集器定义在Collectors中,由Java自身实现我们可以直接使用)
- 主要作用如下:
将流元素归约和汇总为一个值
元素分组
元素分区
具体使用
预先定义一些类用来做示例
public class Menu {
private String name;
private double weight;
public Menu(String name, double weight) {
this.name = name;
this.weight = weight;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
@Override
public String toString() {
return "Menu{" +
"name='" + name + '\'' +
", weight=" + weight +
'}';
}
}
import Java8.chapter3_stream.operate.Menu;
import com.google.common.collect.Lists;
import static java.util.stream.Collectors.*;
public class App {
public static List
1 归约和汇总
1.1 counting() 计算数量总和的收集器
//计算数量
Long total = list.stream().map(Menu::getWeight).collect(counting());
//等同写法
long total2 = list.stream().map(Menu::getWeight).count();
System.out.println("===t1===" + total + ",===t2===" + total2);
结果:===t1===6,===t2===6
1.2 maxBy&minBy 查找流中的最大值和最小值
//查找流中的最大值
Optional max = list.stream().map(Menu::getWeight).collect(maxBy(Double::compare));
//等同写法
Optional max2 = list.stream().map(Menu::getWeight).reduce(Double::max);
//这是reduce独有的,maxBy不存在初始值
Double max3 = list.stream().map(Menu::getWeight).reduce(0D, Double::max);
//查找流中的最小值
Optional min = list.stream().map(Menu::getWeight).collect(minBy(Double::compare));
//等同写法
Optional min2 = list.stream().map(Menu::getWeight).reduce(Double::min);
//这是reduce独有的,minBy不存在初始值
Double min3 = list.stream().map(Menu::getWeight).reduce(1D, Double::min);
System.out.println("===max==="+max+",===max2==="+max2+",===max3==="+max3);
System.out.println("===min==="+min+",===min2==="+min2+",===min3==="+min3);
结果:
===max===Optional[8.88],===max2===Optional[8.88],===max3===8.88
===min===Optional[0.08],===min2===Optional[0.08],===min3===0.08
1.3 汇总(Collectors提供了summingInt、summingDouble、summingLong专门处理对应的三种类型,并且提供了summarizingInt、summarizingDouble、summarizingLong来汇总所有操作)
//汇总 这是处理double另外两个同理
//求和
Double doubleSum = list.stream().collect(summingDouble(Menu::getWeight));
//求平均数
Double averageWeight = list.stream().collect(averagingDouble(Menu::getWeight));
System.out.println("===doubleSum===" + doubleSum + ",===averageWeight===" + averageWeight);
//将汇总操作放在一个收集器进行
DoubleSummaryStatistics doubleSummaryStatistics = list.stream().collect(summarizingDouble(Menu::getWeight));
System.out.println(doubleSummaryStatistics.toString());
结果:
===doubleSum===22.88,===averageWeight===3.813333333333333
DoubleSummaryStatistics{count=6, sum=22.880000, min=0.080000, average=3.813333, max=8.880000}
1.4 连接字符串(Collectors提供了joining方法来进行字符串的连接,并且可以重载连接的字符)
//连接字符串
String printStr = list.stream().map(Menu::getName).collect(joining(","));
System.out.println("打印结果:"+printStr);
结果:
打印结果:fish,apple,beaf,meat,meat,chop
1.5 广义的规约汇总(上面这些例子是它的特殊情况) reducing()
//reducing
double sum = list.stream().collect(reducing(0d, Menu::getWeight, Double::sum));
System.out.println("===sum===" + sum);
//相同效果
Double sum1 = list.stream().mapToDouble(Menu::getWeight).sum();
System.out.println("===sum1===" + sum1);
结果:
===sum===22.880000000000003
===sum1===22.88
2 分组
2.1 多级分组
//按name分类
Map> listMap = list.stream().collect(groupingBy(Menu::getName));
System.out.println(listMap);
//按weight分类
Map> collect = list.stream().collect(groupingBy(
menu -> {
if (menu.getWeight() > 0.9) {
return CaloricLevel.FAT;
} else {
return CaloricLevel.DIET;
}
}));
System.out.println(collect);
//多级分组
Map>> collect1 = list.stream().collect(groupingBy(Menu::getName, groupingBy(menu -> {
if (menu.getWeight() > 0.9) {
return CaloricLevel.FAT;
} else {
return CaloricLevel.DIET;
}
})));
System.out.println(collect1);
2.2 按子组收集数据
//按子组收集数据
Map collect2 = list.stream().collect(groupingBy(Menu::getName, counting()));
Map collect3 = list.stream().collect(groupingBy(Menu::getName, collectingAndThen(maxBy(Comparator.comparingDouble(Menu::getWeight)), Optional::get)));
Map> collect4 = list.stream().collect(groupingBy(Menu::getName, mapping(menu -> {
if (menu.getWeight() > 0.9) {
return CaloricLevel.FAT;
} else {
return CaloricLevel.DIET;
}
}, toSet())));
System.out.println(collect2);
System.out.println(collect3);
System.out.println(collect4);
2.3 分区(是分组的特殊情况,key分为true和false两种情况)
Map> collect5 = list.stream().collect(partitioningBy(m -> m.getWeight() > 0.8));
System.out.println(collect5);