如何在 Java 流中按组应用筛选

2022-09-01 10:27:51

如何首先分组,然后使用 Java 流应用过滤?

示例:考虑以下类:我想按部门对薪水大于 2000 的员工列表进行分组。Employee

public class Employee {
    private String department;
    private Integer salary;
    private String name;

    //getter and setter

    public Employee(String department, Integer salary, String name) {
        this.department = department;
        this.salary = salary;
        this.name = name;
    }
}   

这就是我如何做到这一点

List<Employee> list   = new ArrayList<>();
list.add(new Employee("A", 5000, "A1"));
list.add(new Employee("B", 1000, "B1"));
list.add(new Employee("C", 6000, "C1"));
list.add(new Employee("C", 7000, "C2"));

Map<String, List<Employee>> collect = list.stream()
    .filter(e -> e.getSalary() > 2000)
    .collect(Collectors.groupingBy(Employee::getDepartment));  

输出

{A=[Employee [department=A, salary=5000, name=A1]],
 C=[Employee [department=C, salary=6000, name=C1], Employee [department=C, salary=7000, name=C2]]}

由于B部门没有工资超过2000的雇员。因此,部门B没有密钥:但实际上,我希望该密钥具有空列表 -

预期输出

{A=[Employee [department=A, salary=5000, name=A1]],
 B=[],
 C=[Employee [department=C, salary=6000, name=C1], Employee [department=C, salary=7000, name=C2]]}

我们怎样才能做到这一点?


答案 1

您可以使用自 Java-9 以来引入的 Collectors.filtering API 来实现以下目的:

Map<String, List<Employee>> output = list.stream()
            .collect(Collectors.groupingBy(Employee::getDepartment,
                    Collectors.filtering(e -> e.getSalary() > 2000, Collectors.toList())));

API 说明中的重要内容

  • filtering() 收集器在多级缩减中使用时最有用,例如 或 的下游。groupingBypartitioningBy

  • 筛选收集器不同于流的操作。filter()


答案 2

nullpointer的答案显示了直截了当的前进方向。如果你不能更新到Java 9,没问题,这个收集器不是魔法。下面是一个 Java 8 兼容版本:filtering

public static <T, A, R> Collector<T, ?, R> filtering(
    Predicate<? super T> predicate, Collector<? super T, A, R> downstream) {

    BiConsumer<A, ? super T> accumulator = downstream.accumulator();
    return Collector.of(downstream.supplier(),
        (r, t) -> { if(predicate.test(t)) accumulator.accept(r, t); },
        downstream.combiner(), downstream.finisher(),
        downstream.characteristics().toArray(new Collector.Characteristics[0]));
}

您可以将其添加到代码库中,并以与 Java 9 的对应代码相同的方式使用它,因此,如果您使用的是 .import static


推荐