Java 12中引入的Collector.teeing
特性是对Java流API中Collector
接口的一个强大补充。
teeing()方法
teeing()
是Collectors
类的一个静态方法,用于返回一个将两个Collector
操作的结果组合起来的Collector
。传递给生成的收集器的每个元素都会由两个下游收集器进行处理,然后使用指定的合并函数将它们的结果合并为最终结果。
语法
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
)
说明
Collector.teeing
方法接受三个参数:
- •
Collector<? super T,?, R1> downstream1
:第一个下游收集器,用于从流中收集元素。 - •
Collector<? super T,?, R2> downstream2
:第二个下游收集器,同样用于从流中收集元素。 - •
BiFunction<? super R1,? super R2, R> merger
:用于合并第一个和第二个收集器结果的合并函数。
生成的收集器函数执行以下操作:
- • supplier(供应器):创建一个结果容器,其中包含通过调用每个收集器的供应器获得的结果容器。
- • accumulator(累加器):使用其结果容器和输入元素调用每个收集器的累加器。
- • combiner(组合器):使用两个结果容器调用每个收集器的组合器。
- • finisher(完成器):使用其结果容器调用每个收集器的完成器,然后调用提供的合并函数并返回其结果。
如果两个下游收集器都是无序的,那么生成的收集器具有Collector.Characteristics.UNORDERED
特性;如果两个下游收集器都是并发的,那么生成的收集器具有Collector.Characteristics.CONCURRENT
特性。
示例代码
我们考虑这样一个场景,有一个Person
对象的列表。
record Person(String name, String city, int age){}
示例1:从Person
对象列表中找出最小和最大年龄。
public static void main(String[] args) {
List<Person> people = List.of(new Person("Alex", "Paris", 32),
new Person("Martin", "Paris", 24),
new Person("Tim", "Paris", 23),
new Person("Emilie", "Berlin", 25),
new Person("Albert", "Chicago", 24),
new Person("Mateo", "Madrid", 25),
new Person("Adrien", "Barcelone", 27));
var minMaxAge = people.stream().collect(
Collectors.teeing(
Collectors.minBy(Comparator.comparingInt(Person::age)),
Collectors.maxBy(Comparator.comparingInt(Person::age)),
(min, max) -> "Min = " + min.get() + ", Max = " + max.get() // 合并
)
);
System.out.println(minMaxAge);
}
输出:
Min = Person[name=Tim, city=Paris, age=23], Max = Person[name=Alex, city=Paris, age=32]
示例1:找出居住在巴黎的人员列表以及年龄为24岁的人员列表
public static void main(String[] args) {
List<Person> people = List.of(new Person("Alex", "Paris", 32),
new Person("Martin", "Paris", 24),
new Person("Tim", "Paris", 23),
new Person("Emilie", "Berlin", 25),
new Person("Albert", "Chicago", 24),
new Person("Mateo", "Madrid", 25),
new Person("Adrien", "Barcelone", 27));
List<List<Person>> result = people.stream()
.collect(Collectors.teeing(
Collectors.filtering(p -> p.city().equals("Paris"),
Collectors.toList()),
Collectors.filtering(p -> 24 == p.age(),
Collectors.toList()),
List::of
));
System.out.println(result);
}
输出:
[[Person[name=Alex, city=Paris, age=32],
Person[name=Martin, city=Paris, age=24],
Person[name=Tim, city=Paris, age=23]],
[Person[name=Martin, city=Paris, age=24],
Person[name=Albert, city=Chicago, age=24]]]
示例1:统计居住在巴黎的人数以及流中发出的人员数量
public static void main(String[] args) {
List<Person> people = List.of(new Person("Alex", "Paris", 32),
new Person("Martin", "Paris", 24),
new Person("Tim", "Paris", 23),
new Person("Emilie", "Berlin", 25),
new Person("Albert", "Chicago", 24),
new Person("Mateo", "Madrid", 25),
new Person("Adrien", "Barcelone", 27));
List<Long> result = people.stream()
.collect(Collectors.teeing(
Collectors.filtering(p -> p.city().equals("Paris"),
Collectors.counting()),
Collectors.counting(),
List::of)
);
System.out.println(result);
}
输出:
[3, 7]
结论
Collectors.teeing()
方法是一个强大的工具,用于在一次遍历中执行多个流操作,使你的代码更加高效且富有表现力。
没有回复内容