【问题标题】:How to filter a list of object by multiple fields in Java?如何在Java中按多个字段过滤对象列表?
【发布时间】:2019-10-21 14:55:52
【问题描述】:

我想按多个字段过滤对象列表,但这些用于过滤的字段可以更改。例如;

假设我们有一个具有一些属性的 Employee 类:

@Data
public class Employee {
   private Integer id;
   private Integer age;
   private String gender;
   private String firstName;
   private String lastName;

}

编写有时按年​​龄和性别或有时仅按名字过滤的方法的最佳方法是什么? (可以复制样本,即对于这个例子,它有 5 个属性,所以有 5!= 120 种可能性) 是否可以使用 lambda 或 Java 中的其他东西进行编码?

附: : 任何可能性都不是预定义的。无论请求来自什么,它都应该被它过滤。我相信下面的例子会让这个问题变得清晰:

假设我们有一个 Filter 对象,它与 Employee 的属性相同。如果给定了年龄而其他为空,则此服务将仅按年龄过滤。或者只给出性别和名字,它应该按标准获得员工。

【问题讨论】:

  • 创建Set<Predicate<Employee>> 并在每次处理流时选择一个随机谓词。
  • 有哪些可能的组合?它们是预定义的还是以某种随机顺序选择的?
  • 没有预定义可能的组合,它可能是 n! .实际上,我会将其用作服务。所以无论请求来自什么,它都应该被它过滤。
  • 请求的内容是什么?
  • @okduman 是否愿意定义一个enum,它将这五个属性(类型)映射到一个特定于过滤的Predicate<Employee>?或者过滤条件是否也是您请求的一部分?在这种情况下,你会很想知道,你是如何设计你的 Request 对象的?

标签: java generics lambda filter


【解决方案1】:

如果您知道需要过滤的内容,则可以组合谓词。 假设您要过滤名字以J 开头、年龄超过 37 岁的员工。

Predicate<Employee> p = e -> e.getFirstName().startsWith("J");
p = p.and(e -> e.getAge() > 37);

您现在可以在过滤器中使用谓词p。您只需要根据所需条件构建最终谓词即可。

【讨论】:

  • 其实这就是我们不从请求中得到什么。这就是为什么有这么多的可能性。
  • @okduman 你的意思是用户可以搜索他们能想到的任何东西,提供无限的可能性?那么你将无法使用流来处理它。如果您至少有一些预定义的搜索词,那么谓词的数量就会少很多。
【解决方案2】:

您可能想要使用filter 函数。此函数的工作方式是,如果您的表达式计算结果为 true,它将返回到结果流。

一个示例 sn-p 将是:

//Assuming employeeList is an ArrayList of Employee:
employeeList.stream().filter((e) -> e.age>25 && "M".equals(e.gender)); //Gives you a stream with all the male employees older than 25.

这里有一些reading material 给你!特别是“2.3 For multiple condition”。部分。

希望这会有所帮助!

【讨论】:

    【解决方案3】:

    您可以为每个属性实现某些搜索功能,例如

    • 对于年龄,可能的过滤器'Equal''Greater than''Less than'

    • 对于姓氏,过滤器'is equal''begins with''ends with'.

    • 对于性别'is male'

    您可以在 Employee 类中添加如下内容:

    public static Predicate<Employee> ageEQ(int a) {
        return e -> e.getAge() == a;
    }
    public static Predicate<Employee> ageGT(int a) {
        return e -> e.getAge() > a;
    }
    public static Predicate<Employee> ageLT(int a) {
        return e -> e.getAge() < a;
    }
    public static Predicate<Employee> isMale() {
        return e -> e.getGender().equals("M");
    }
    public static Predicate<Employee> lastNameEQ(String name) {
        return e -> e.getLastName().equals(name);
    }
    public static Predicate<Employee> lastNameStartsWith(String name) {
        return e -> e.getLastName().startsWith(name);
    }
    

    还有一份员工名单:

    List<Employee> list = new ArrayList<>();
        list.add(new Employee(1,22,"M","Aaa","Bar"));
        list.add(new Employee(2,33,"F","Ccc","Ddd"));
        list.add(new Employee(3,44,"M","Eee","Fff"));
        list.add(new Employee(4,55,"F","Ggg","Hhh"));
        list.add(new Employee(5,66,"F","Mmm","Nnn"));
    

    例如过滤所有 40 岁以上的女性员工:

    list.stream()
        .filter(Employee.ageGT(40).and(Employee.isMale().negate()))
        .forEach(System.out::println);
    

    假设您的请求类似于 ?age>40&male=false ...

    【讨论】:

      猜你喜欢
      • 2016-10-27
      • 2020-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多