Java 12的新功能:Teeing收集器

在本文中,我们将介绍Java 12中引入的新收集器。此新功能未在官方JEP中宣布,因为这是一个较小的更改请求,标题为“ 创建收集器,它将其他两个收集器的结果合并 ”。 它旨在合并两个收集器的结果。


所有有趣的事情-切入


如果您仍然不知道什么是收藏家
收集器是用于将流转换为另一数据结构的特殊类。 例如,在list
 list = Stream.of(1,2,3).collect(Collectors.toList()); //     1, 2  3 

这是一个无用的示例,因为它会创建一个新流并立即对其进行转换。 可以考虑使用收藏家

该文件


单击此处查看Collectors#teeing 。 根据官方文件:
“ ...返回由两个下级收集器组成的收集器。 转移到结果收集器的每个元素都由两个下级收集器处理,然后使用将它们连接到最终结果的特殊功能对其结果进行合并。”
原来的
“ ...返回一个由两个下游收集器组成的收集器。传递给结果收集器的每个元素都由两个下游收集器处理,然后使用指定的合并功能将其结果合并为最终结果。”
方法标题:

 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) 

有趣的事实


这是一个发球区域 (英语发球):



发球区域来自发球区域。 根据Wikipedia的说法,“ T型管是用于组合(或分割)流体流(在这种情况下,我们指的是流,流-流/流,注释翻译器)的最常见的配件(管道的连接部分,大约是翻译器)。”
提出了其他名称:平分(分成2部分),双工,分叉(划分),复制器,扇出(划分),分接,解压缩,collectionToBothAndThen,biCollecting,扩展(扩展),分叉等。
核心开发人员评定的所有替代方案都可以在这里找到

使用范例


我已经编译了三个使用不同复杂程度代码的示例。

来宾清单


我们从流中的对象列表中提取两种不同类型的信息。 每位客人必须接受邀请并可以带领家人。 我们想知道谁确认了预订以及参与者总数 (包括客人和家庭成员)。

 var result = Stream.of( // Guest(String name, boolean participating, Integer participantsNumber) new Guest("Marco", true, 3), new Guest("David", false, 2), new Guest("Roger",true, 6)) .collect(Collectors.teeing( //  ,    ,    Collectors.filtering(Guest::isParticipating, //        Collectors.mapping(o -> o.name, Collectors.toList())), //  ,       Collectors.summingInt(Guest::getParticipantsNumber), //      , //    EventParticipation::new )); System.out.println(result); //  // EventParticipation { guests = [Marco, Roger], // total number of participants = 11 } 


来宾
 class Guest { private String name; private boolean participating; private Integer participantsNumber; public Guest(String name, boolean participating, Integer participantsNumber) { this.name = name; this.participating = participating; this.participantsNumber = participantsNumber; } public boolean isParticipating() { return participating; } public Integer getParticipantsNumber() { return participantsNumber; } } 


活动参与
 class EventParticipation { private List<String> guestNameList; private Integer totalNumberOfParticipants; public EventParticipation(List<String> guestNameList, Integer totalNumberOfParticipants) { this.guestNameList = guestNameList; this.totalNumberOfParticipants = totalNumberOfParticipants; } @Override public String toString() { return "EventParticipation { " + "guests = " + guestNameList + ", total number of participants = " + totalNumberOfParticipants + " }"; }} 


在两个不同的列表中过滤名称


在此示例中,我们根据过滤器将名称流分成两个列表。

 var result = Stream.of("Devoxx", "Voxxed Days", "Code One", "Basel One", "Angular Connect") .collect(Collectors.teeing( //   Collectors.filtering(n -> n.contains("xx"), Collectors.toList()), //   Collectors.filtering(n -> n.endsWith("One"), Collectors.toList()), //  -       (List<String> list1, List<String> list2) -> List.of(list1, list2) )); System.out.println(result); // -> [[Devoxx, Voxxed Days], [Code One, Basel One]] 

计算并添加数字流


您可能已经在博客上看到了类似的示例,该示例结合了总和和计数以获得平均值。 这个例子不需要Teeing ,您可以简单地使用AverageInt和一个简单的收集器。

下面的示例使用Teeing函数返回两个值:

 var result = Stream.of(5, 12, 19, 21) .collect(Collectors.teeing( //   Collectors.counting(), //   Collectors.summingInt(n -> Integer.valueOf(n.toString())), // : (count, sum) -> new Result(count, sum); Result::new )); System.out.println(result); // -> {count=4, sum=57} 

结果
 class Result { private Long count; private Integer sum; public Result(Long count, Integer sum) { this.count = count; this.sum = sum; } @Override public String toString() { return "{" + "count=" + count + ", sum=" + sum + '}'; }} 


可能的陷阱


地图条目

许多示例使用Map.Entry存储BiFunction的结果。 请不要这样做,因为您不能在Map存储最后一个参数。 Java Core中没有用于存储两个值的标准对象-您必须自己创建它。

关于Java 12新功能的所有信息


在此演示文稿中,您可以找到有关Java 12的更多信息和有趣的事实。

成功的收藏品!

Source: https://habr.com/ru/post/zh-CN445622/


All Articles