You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Java Streams基于动态条件列表过滤Employee集合?

问题描述

我有一个包含Employee对象列表的Person类实例,Employee具备name、age、dept、city属性。另有一个动态的Criteria列表,可包含1个或多个条件。需要基于此列表过滤Employee列表:当条件类型为AGE时对比emp.age;类型为CITY时对比emp.city,其他类型同理匹配对应属性。相关类定义如下(需补全getter/setter以支持Stream操作):

public class Person {
    private List<Employee> empList;
    public Person(List<Employee> empList) {
        super();
        this.empList = empList;
    }
    public List<Employee> getEmpList() {
        return empList;
    }
    public void setEmpList(List<Employee> empList) {
        this.empList = empList;
    }
}
public class Employee {
    private String name;
    private int age;
    private String city;
    private String dept;
    public Employee(String name, int age, String city, String dept) {
        super();
        this.name = name;
        this.age = age;
        this.city = city;
        this.dept = dept;
    }
    // 补全getter方法
    public String getName() { return name; }
    public int getAge() { return age; }
    public String getCity() { return city; }
    public String getDept() { return dept; }
}
public class Criteria {
    private CriteriaType type;
    private String value;
    public Criteria(CriteriaType type, String value) {
        super();
        this.type = type;
        this.value = value;
    }
    // 补全getter方法
    public CriteriaType getType() { return type; }
    public String getValue() { return value; }
}
public enum CriteriaType {  
    NAME, CITY, AGE, DEPT
}
public class FilterEmployee {
    public static void main(String[] args) {
        Employee emp1 = new Employee("John", 30, "Dallas", "HR");
        Employee emp2 = new Employee("Steve", 31, "Austin", "HR");
        Employee emp3 = new Employee("Andrew", 25, "Houston", "Finance");
        Employee emp4 = new Employee("Mike", 30, "Dallas", "HR");
        List<Employee> empList = new ArrayList<>();
        empList.add(emp1);
        empList.add(emp2);
        empList.add(emp3);
        empList.add(emp4);
        Person personObj = new Person(empList);
        Criteria c1 = new Criteria(CriteriaType.CITY, "Dallas");
        Criteria c2 = new Criteria(CriteriaType.NAME, "Mike");
        List<Criteria> criteriaList = new ArrayList<>();
        criteriaList.add(c1);
        criteriaList.add(c2);
        // 需基于Criteria列表过滤包含Employee列表的Person对象
    }
}

请问是否存在简洁的方式,使用Java Streams完成该条件对比与过滤操作?

解决方案:Java Streams动态条件过滤

可以用Java Streams结合Predicate简洁实现动态条件过滤,核心是将每个Criteria转换为对应的断言,再组合所有断言进行过滤。

实现步骤

  1. 转换单个Criteria为Predicate:根据CriteriaType的不同,创建对应的Predicate<Employee>,匹配Employee的对应属性。注意AGE类型需要将字符串值转为整数再对比。
  2. 组合所有Predicate:将多个条件用Predicate.and()组合,确保只有满足所有条件的Employee才会被保留。
  3. Stream过滤:从Person实例中获取员工列表,通过Stream的filter方法应用组合后的断言,最后收集结果。

完整代码实现

修改FilterEmployee的main方法,添加过滤逻辑:

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class FilterEmployee {
    public static void main(String[] args) {
        Employee emp1 = new Employee("John", 30, "Dallas", "HR");
        Employee emp2 = new Employee("Steve", 31, "Austin", "HR");
        Employee emp3 = new Employee("Andrew", 25, "Houston", "Finance");
        Employee emp4 = new Employee("Mike", 30, "Dallas", "HR");
        List<Employee> empList = new ArrayList<>();
        empList.add(emp1);
        empList.add(emp2);
        empList.add(emp3);
        empList.add(emp4);
        Person personObj = new Person(empList);
        Criteria c1 = new Criteria(CriteriaType.CITY, "Dallas");
        Criteria c2 = new Criteria(CriteriaType.NAME, "Mike");
        List<Criteria> criteriaList = new ArrayList<>();
        criteriaList.add(c1);
        criteriaList.add(c2);

        // 1. 将每个Criteria转换为Predicate
        List<Predicate<Employee>> predicates = criteriaList.stream()
                .map(criteria -> {
                    switch (criteria.getType()) {
                        case NAME:
                            return emp -> emp.getName().equals(criteria.getValue());
                        case CITY:
                            return emp -> emp.getCity().equals(criteria.getValue());
                        case AGE:
                            return emp -> emp.getAge() == Integer.parseInt(criteria.getValue());
                        case DEPT:
                            return emp -> emp.getDept().equals(criteria.getValue());
                        default:
                            return emp -> true; // 默认匹配所有
                    }
                })
                .collect(Collectors.toList());

        // 2. 组合所有Predicate:所有条件必须同时满足
        Predicate<Employee> combinedPredicate = predicates.stream()
                .reduce(Predicate::and)
                .orElse(emp -> true); // 如果没有条件,返回所有员工

        // 3. 过滤员工列表
        List<Employee> filteredEmps = personObj.getEmpList().stream()
                .filter(combinedPredicate)
                .collect(Collectors.toList());

        // 测试输出:应该只输出Mike
        filteredEmps.forEach(emp -> System.out.println(emp.getName()));
    }
}

说明

  • 若需要支持或条件,只需将Predicate::and替换为Predicate::or即可;
  • 对于AGE类型的条件,要确保传入的value是合法整数,否则会抛出NumberFormatException,可以根据需求添加异常处理;
  • 补全getter是因为Stream操作需要访问Employee和Criteria的私有属性,这是Java封装性的要求。

内容的提问来源于stack exchange,提问作者Soni

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 04:09:56