314. Java Stream API - 使用 Collectors.partitioningBy() 分区元素
在 Java Stream API 中,Collectors 工厂类提供了多种创建映射的模式,其中之一是通过布尔值作为键来分区流中的元素。这个分区功能是通过 partitioningBy() 工厂方法实现的。
✅ partitioningBy() 简介
partitioningBy() 会根据一个布尔值来将流中的元素分成两个部分,返回一个 Map<Boolean, List<T>>。true 和 false 分别作为键,流中的每个元素会被放入对应的列表中,具体分到哪个键由给定的 谓词(predicate) 决定。
简而言之,partitioningBy() 是一种基于条件将流中的元素划分为两组的方法。条件是通过谓词来判断的,谓词作为 partitioningBy() 的参数传入。
✅ 示例:根据字符串长度分组
假设我们有一个字符串列表,我们想根据每个字符串的长度来将其分组:长度大于 4 的放到 true 组,长度不大于 4 的放到 false 组。以下是如何实现的代码:
Collection<String> strings = List.of("one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
"ten", "eleven", "twelve");
Map<Boolean, List<String>> map = strings.stream()
.collect(Collectors.partitioningBy(s -> s.length() > 4));
map.forEach((key, value) -> System.out.println(key + " :: " + value));
运行结果:
false :: [one, two, four, five, six, nine, ten]
true :: [three, seven, eight, eleven, twelve]
在这个示例中,partitioningBy() 使用了一个谓词 s -> s.length() > 4 来将字符串分成两组:
-
false组:长度小于等于 4 的字符串。 -
true组:长度大于 4 的字符串。
✅ 使用下游收集器(Downstream Collector)
partitioningBy() 不仅可以使用一个简单的谓词来进行分区,还可以进一步定制每个分区的收集方式。它支持传入一个 下游收集器(downstream collector),用于对每个分区中的元素进行额外的操作。
例如,我们可以对每个分区的字符串进行排序。通过给 partitioningBy() 传入一个排序的收集器,我们就能按要求对每个分区进行操作。
示例:对每个分区的元素进行排序
Map<Boolean, List<String>> map = strings.stream()
.collect(Collectors.partitioningBy(s -> s.length() > 4,
Collectors.toList()));
map.forEach((key, value) -> {
List<String> sortedList = value.stream()
.sorted()
.collect(Collectors.toList());
System.out.println(key + " :: " + sortedList);
});
运行结果:
false :: [five, four, nine, one, six, ten, two]
true :: [eight, eleven, seven, three, twelve]
在这个例子中,我们使用了 Collectors.toList() 作为下游收集器,并在 partitioningBy() 之后对每个分区中的元素进行排序。false 和 true 组中的字符串按照字母顺序排列。
✅ 总结
-
partitioningBy()的作用:将流中的元素基于一个谓词条件分成两个组,生成一个Map<Boolean, List<T>>。 -
谓词的作用:谓词决定每个元素应分配到
true组还是false组。 -
下游收集器的使用:
partitioningBy()可以接受一个下游收集器,用于对每个分区中的元素进行额外的操作,如排序、聚合等。 - 常见应用场景:这个方法非常适合用于二分类分区操作,例如根据条件分割数据,或者在分区后执行不同的操作。
通过 partitioningBy(),你可以轻松地对流中的数据进行分组,并根据需要进一步处理每个分组的数据。