在Java中如何使用Stream.collect(Collectors.partitioningBy)进行条件分区_Stream分区技巧

Stream.collect(Collectors.partitioningBy) 可按布尔条件将流元素分为两组,返回Map,适用于奇偶分离、成年判断等二元分类场景,并支持下游收集器进行数量统计、去重等聚合操作。

在Java中,Stream.collect(Collectors.partitioningBy) 是一种基于布尔条件将流元素分成两个组的便捷方式。它返回一个 Map>,其中键为 truefalse,分别对应满足和不满足条件的元素列表。这个方法特别适合做二元分类,比如奇偶数分离、年龄是否成年、字符串是否为空等场景。

基本语法与使用方式

partitioningBy 接收一个 Predicate 函数式接口作为参数,根据该条件对元素进行分区:

Stream.collect(Collectors.partitioningBy(predicate))

例如,将数字列表按奇偶性分区:

  • 定义一个整数列表并转换为流
  • 使用 partitioningBy(n -> n % 2 == 0) 判断是否为偶数
  • 收集结果到 Map 中,true 对应偶数,false 对应奇数

代码示例:

List numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
Map> partitioned = numbers.stream()
    .collect(Collectors.partitioningBy(n -> n % 2 == 0));

System.out.println("偶数: " + partitioned.get(true)); // [2, 4, 6]
System.out.println("奇数: " + partitioned.get(false)); // [1, 3, 5]

结合下游收集器进行更复杂操作

除了默认返回 List,还可以传入下游收集器(downstream collector)来定制每个分区的数据结构或聚合结果。

例如,统计每个分区的数量:

Map counts = numbers.stream()
    .collect(Collectors.partitioningBy(n -> n > 3, Collectors.counting()));

System.out.println("大于3的个数: " + counts.get(true));  // 3
System.out.println("不大于3的个数: " + counts.get(false)); // 3

或将分区结果转为集合去重:

Map> grouped = numbers.stream()
    .collect(Collectors.partitioningBy(n -> n % 2 == 0, Collectors.toSet()));

实际应用场景举例

假设有一个用户类:

class User {
    String name;
    int age;
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public boolean isAdult() { return age >= 18; }
}

我们可以按是否成年分区:

List users = Arrays.asList(
    new User("Alice", 20),
    new User("Bob", 17),
    new User("Charlie", 25)
);

Map> adultGroup = users.stream()
    .collect(Collectors.partitioningBy(User::isAdult));

List adults = adultGroup.get(true);
List minors = adultGroup.get(false);

这样可以清晰地分离出成年人和未成年人,便于后续处理,如权限控制、数据展示等。

基本上就这些。partitioningBy 简洁明了地实现二分逻辑,配合下游收集器能灵活应对多种聚合需求,是Stream API中非常实用的工具之一。