如何实现动态运行时查询来过滤Java对象流

问题描述 投票:0回答:1

假设我有

List
以下类型的对象:

public class Employee {
    private String emplId;
    private Name name;
    private String dept;
    private String city;
}

我有以下清单:

List<Employee> empLst = Arrays.asList(
        new Employee("1", "henry", "10", "Boston"),
        new Employee("2", "Foster", "10", "san jose"),
        new Employee("3", "Rick", "10", "sfo"),
        new Employee("4", "Ban", "20", "Boston"),
        new Employee("5", "Zen", "20", "Ale"),
        new Employee("6", "Ken", "30", "sfo")
);

如何实现接受员工对象并过滤与查询对象值匹配的列表的搜索?

GetEmplList(new Employee().setCity("Boston")); // returns both #1 and #4 employees
GetEmplList(new Employee().setCity("Boston").setDept("20")); // returns only #4 employee
GetEmplList(new Employee().setName("Ken")); // returns only #6 employees

我不想要类似以下编译时过滤器的东西:

empLst.stream()
     .filter(e -> e.getCity().equalsIgnoreCase("Boston"))
     .forEach(e -> System.out.println(e.getName()));
java filter java-stream
1个回答
0
投票

您需要一个

Predicate
将元素与提供的“示例”相匹配。示例中为
null
的属性应视为匹配。

import java.util.function.Predicate;

public class ExampleBasedFilter implements Predicate<Employee> {

  private final Employee example;

  public ExampleBasedFilter(Employee example) {
    this.example = example;
  }

  @Override
  public boolean test(Employee employee) {
    return match(example.getEmplId(), employee.getEmplId())
            && match(example.getCity(), employee.getCity())
            && match(example.getName(), employee.getName())
            && match(example.getDept(), employee.getDept());
  }

  private static boolean match(Object exampleProperty, Object propertyToTest) {
    if (exampleProperty == null) {
      return true;
    }
    return exampleProperty.equals(propertyToTest);
  }
}

用途:

Employee example = new Employee(null, null, "20", "Boston");
List<Employee> filteredResult = empLst.stream()
        .filter(new MatchByExample(example))
        .toList();
System.out.println(filteredResult);
//prints the employee with id 4

或者使用反射更通用地实现

Predicate
,它可以适用于任何类:

import java.lang.reflect.Field;
import java.util.function.Predicate;

public class GenericExampleBasedFilter<T> implements Predicate<T> {

  private final T example;

  public GenericExampleBasedFilter(T example) {
    this.example = example;
  }

  @Override
  public boolean test(T t) {
    for (Field field : example.getClass().getDeclaredFields()) {
      field.setAccessible(true);
      try {
        Object exampleValue = field.get(example);
        Object testValue = field.get(t);
        if (!match(exampleValue, testValue)) {
          return false;
        }
      } catch (IllegalAccessException e) {
        throw new RuntimeException(e);
      } finally {
        field.setAccessible(false);
      }
    }
    return true;
  }

  private static boolean match(Object exampleProperty, Object propertyToTest) {
    if (exampleProperty == null) {
      return true;
    }
    return exampleProperty.equals(propertyToTest);
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.