查看原文
其他

JDK 12 Collectors.teeing 实例介绍

ImportNew ImportNew 2019-11-26

(给ImportNew加星标,提高Java技能)

编译:ImportNew/唐尤华

dzone.com/articles/introducing-jdk-12-teeing


用JDK 12开球(Tee Off 一语双关)!


本文通过实例简要介绍了 JDK 12 Teeing Collector。

 

JDK 12开始,可以用 Collectors.teeing() 合并两个 collector 的结果。teeing() 的语法如下:


public static <T, R1, R2, R> Collector<T, ?, R> teeing(
Collector<? super T, ?, R1> downstream1,
Collector<? super T, ?, R2> downstream2,
BiFunction<? super R1, ? super R2, R> merger
)



teeing() 的结果是一个 Collector,组合了传入的两个下游(downstream) collector。生成的结果 collector 中,每个元素都经过了两个下游 collector 处理,然后使用指定的 BiFunction 合并成最终结果。


让我们看一个经典问题。下面这个 class 记录了一个整数 stream 中的 count(个数)和 sum(总和):


public class CountSum {
private final Long count;
private final Integer sum;
public CountSum(Long count, Integer sum) {
this.count = count;
this.sum = sum;
}
...
}


可以像下面这样,调用 teeing() 得到需要结果:


CountSum countsum = Stream.of(2, 11, 1, 5, 7, 8, 12)
.collect(Collectors.teeing(
counting(),
summingInt(e -> e),
CountSum::new));


这里对 stream 中的每个元素应用(counting() 和 summingInt())两个 collector,并且把结果合并为 CountSum 实例:


CountSum{count=7, sum=46}


让我们接着看另一个问题。这次,MinMax class 存储了整数 stream 中的最大值和最小值:


public class MinMax {
private final Integer min;
private final Integer max;
public MinMax(Integer min, Integer max) {
this.min = min;
this.max = max;
}
...
}


现在,可以像下面这样获取信息:


MinMax minmax = Stream.of(2, 11, 1, 5, 7, 8, 12)
.collect(Collectors.teeing(
minBy(Comparator.naturalOrder()),
maxBy(Comparator.naturalOrder()),
(Optional<Integer> a, Optional<Integer> b)
-> new MinMax(a.orElse(Integer.MIN_VALUE),
b.orElse(Integer.MAX_VALUE))));


这次,对 stream 中的每个元素应用 collector(minBy() 和 maxBy()),并且把结果合并为 MinMax 实例。


MinMax{min=1, max=12}


最后,考虑下面的 Melon class 和 Melon List:


public class Melon {
private final String type;
private final int weight;
public Melon(String type, int weight) {
this.type = type;
this.weight = weight;
}
...
}
List<Melon> melons = Arrays.asList(new Melon("Crenshaw", 1200),
new Melon("Gac", 3000), new Melon("Hemi", 2600),
new Melon("Hemi", 1600), new Melon("Gac", 1200),
new Melon("Apollo", 2600), new Melon("Horned", 1700),
new Melon("Gac", 3000), new Melon("Hemi", 2600)
);


这里要计算这些 melon 的总重量并列出它们各自的重量。代码如下:


public class WeightsAndTotal {
private final int totalWeight;
private final List<Integer> weights;
public WeightsAndTotal(int totalWeight, List<Integer> weights) {
this.totalWeight = totalWeight;
this.weights = weights;
}
...
}


采用 Collectors.teeing() 来解决,如下所示:


WeightsAndTotal weightsAndTotal = melons.stream()
.collect(Collectors.teeing(
summingInt(Melon::getWeight),
mapping(m -> m.getWeight(), toList()),
WeightsAndTotal::new));


这次使用 summingInt() 和 mapping() collector,结果如下:


WeightsAndTotal {
totalWeight = 19500,
weights = [1200, 3000, 2600, 1600, 1200, 2600, 1700, 3000, 2600]
}


任务达成! 


完整的源代码可在 GitHub 上找到。

github.com/PacktPublishing/Java-Coding-Problems/tree/master/Chapter09/P192_Teeing


推荐阅读

(点击标题可跳转阅读)

Docker 架构原理及简单使用

项目中常用的 19 条 MySQL 优化

Java : 对象不再使用时,为什么要赋值为 null ?


看完本文有收获?请转发分享给更多人

关注「ImportNew」,提升Java技能

好文章,我在看❤️

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存