Как преобразовать if-else, если объединить код блока с несколькими критериями фильтра в критерии одного фильтра с проверкой нуля? - PullRequest
1 голос
/ 24 апреля 2019

У меня есть класс Employee, и есть метод getEmployees(), который возвращает всех возможных сотрудников.Я хочу добавить несколько критериев фильтра к одному и другим and условиям только в том случае, если входящие параметры not null.

Я пробовал следующий подход, который выполняет фильтрацию, но есть несколько if-elseесли происходит цепочка.Есть ли лучший способ уменьшить эту цепочку в один предикат, что-то похожее сделано в динамическая фильтрация .Код цепочки, который у меня есть, выглядит следующим образом:

Класс сотрудника

public class Employee{
    private String fName;
    private String lName;
    private String type;

    //getters & setters

}

If-else, если блок цепочки:

public List<Employee> retrieveEmployees(String searchToken, String fName, String lName, String type){
    //this will retrieve all the available employees 
    List<Employee> employees = getEmployees(); 
    List<Employee> filteredEmployees= new ArrayList<>();

    //perform filtering on the basis of accepted params
    if(searchToken !=null){
        filteredEmployees=employees
        .stream()
        .filter(emp-> emp.getFName().equalsIgnoreCase(searchToken) && emp.getLName().equalsIgnoreCase(searchToken))
        .collect(Collectors.toList());

    }
    else if (fName != null && lName != null && type != null) {
        filteredEmployees=employees
        .stream()
        .filter(emp-> emp.getFName().equalsIgnoreCase(fName) && emp.getLName().equalsIgnoreCase(lName) && emp.getType().equalsIgnoreCase(type))
        .collect(Collectors.toList());
    } else if (type != null && fname != null && lname == null) {
        filteredEmployees=employees
        .stream()
        .filter(emp-> emp.getFName().equalsIgnoreCase(fName) && emp.getType().equalsIgnoreCase(type))
        .collect(Collectors.toList());
    } else if (fname != null && lname != null && type == null) {
        filteredEmployees=employees
        .stream()
        .filter(emp-> emp.getFName().equalsIgnoreCase(fName) && emp.getLName().equalsIgnoreCase(lName))
        .collect(Collectors.toList());
    } else if (lname != null && type != null && fname == null) {
        filteredEmployees=employees
        .stream()
        .filter(emp-> emp.getLName().equalsIgnoreCase(lName) && emp.getType().equalsIgnoreCase(type))
        .collect(Collectors.toList());
    } else if (fname != null && lname == null && type == null) {
        filteredEmployees=employees
        .stream()
        .filter(emp-> emp.getFName().equalsIgnoreCase(fName))
        .collect(Collectors.toList());
    } else if (lname != null && fname == null && type == null) {
        filteredEmployees=employees
        .stream()
        .filter(emp-> emp.getLName().equalsIgnoreCase(lName))
        .collect(Collectors.toList());
    } else if (type != null && fname == null && lname == null) {
        filteredEmployees=employees
        .stream()
        .filter(emp-> emp.getType().equalsIgnoreCase(type))
        .collect(Collectors.toList());
    } else {
        filteredEmployees=getEmployees();
    }


    return filteredEmployees;
}

Я пробовал что-то вроде:но он терпит неудачу, так как сам предикат просто делает or/and, он не удовлетворяет тому, что я сделал в if-else if блоке:

List<Predicate<Employee>> predicates=Arrays.asList(
            e -> e.getFName().equalsIgnoreCase(fName),
            e -> e.getLName().equalsIgnoreCase(lName),
            e -> e.getType().equals(type)
    );

Predicate<Employee> compositePredicate = predicates
    .stream()
    .reduce(w -> true, Predicate::or); //tried with 'and' as well

filteredEmployees= employees
    .stream()
    .filter(compositePredicate)
    .collect(Collectors.toList());

Чего мне не хватает в этом?Какой эффективный подход цепочки предикатов потока может быть применен?

1 Ответ

2 голосов
/ 24 апреля 2019

у вас может быть класс SearchFilter, который будет содержать все ваши поля фильтра, такие как searchToken, fname и т. Д., И еще один Condition, например:

class Condition {
    private Predicate<SearchFilter> searchFilterPredicate;
    private Function<SearchFilter, Predicate<Employee>> function;
}

тогда вы можете определить статический неизменяемый список со всеми условиями:

List<Condition> conditions = Arrays.asList(
    new Condition(sf -> sf.getSearchToken() != null,
                  sf -> emp -> emp.getFName().equalsIgnoreCase(sf.getSearchToken()) && emp.getLName().equalsIgnoreCase(sf.getSearchToken())),
    new Condition(sf -> ObjectUtils.allNotNull(sf.getFname(), sf.getLname(), sf.getType()),
                  sf -> emp-> emp.getFName().equalsIgnoreCase(sf.getFname()) && emp.getLName().equalsIgnoreCase(sf.getLname()) && emp.getType().equalsIgnoreCase(sf.getType()))
    //...
);

и, наконец, retrieveEmployees метод

public List<Employee> retrieveEmployees(String searchToken, String fname, String lname, String type){
    List<Employee> employees = getEmployees();
    SearchFilter searchFilter = new SearchFilter(searchToken, fname, lname, type);

    Optional<Predicate<Employee>> firstCondition = conditions.stream()
            .filter(condition -> condition.getSearchFilterPredicate().test(searchFilter))
            .findFirst()
            .map(condition -> condition.getFunction().apply(searchFilter));

    return firstCondition.map(employeePredicate -> employees.stream()
                .filter(employeePredicate)
                .collect(Collectors.toList()))
            .orElse(employees);
}

Другое решение может проверять каждое поле фильтра и добавлять его для предиката

List<Employee> retrieveEmployees(String searchToken, String fname, String lname, String type){
    List<Employee> employees = getEmployees();
    if(searchToken != null) {
        return employees
                .stream()
                .filter(emp -> emp.getFName().equalsIgnoreCase(searchToken) && emp.getLName().equalsIgnoreCase(searchToken))
                .collect(Collectors.toList());

    }
    Predicate<Employee> predicate = employee -> true;

    if(type != null) {
        predicate = predicate.and(emp -> emp.getType().equalsIgnoreCase(type));
    }
    if(lname != null) {
        predicate = predicate.and(emp -> emp.getLName().equalsIgnoreCase(lname));
    }
    if(fname != null) {
        predicate = predicate.and(emp -> emp.getFName().equalsIgnoreCase(fname));
    }

    return employees.stream()
             .filter(predicate)
             .collect(Collectors.toList());
}
...