Как упростить огромный if-оператор в теле .filter? - PullRequest
0 голосов
/ 11 февраля 2019

Есть ли более понятный и понятный способ выразить это?

    List<LocationVO> listLocation = listLocationAll.stream().filter(l -> {
        boolean ok = true;
        if ( filter.getClient_id() != null && filter.getClient_id().longValue() !=  l.getParent_client_id() ) {
            ok = false;
        }
        if ( filter.getLocation_id() != null && filter.getLocation_id().longValue() !=  l.getLocation_id() ) {
            ok = false;
        }
        if (filter.getLocation_type() != null && (filter.getLocation_type().equals(l.getLocation_type()) == false) ) {
            ok = false;
        }
        return ok;
    }).collect(Collectors.toList());

LocationVO cotains:

public class LocationVO implements Serializable {

    private static final long serialVersionUID = 1L;

    private long location_id;
    private long parent_client_id;
    private String name;
    private String location_type;
    ...
}

Фильтр имеет тип LocationFilter и содержит:

public class LocationFilter implements Serializable {

    private Long client_id;
    private Long location_id;
    private String location_type;
}

Первый оператор if: если для идентификатора клиента был установлен фильтр -> не содержит никакого LocationVO, у которого связанный клиент не имеет этого идентификатора

Второй оператор if: если для местоположения был установлен фильтр ->удалить / отфильтровать все LocationVO, у которых нет этого идентификатора

Третий оператор if: отфильтровать все VO, которые не имеют location_type фильтра.

((Я думаю, ни один из них не устарел ((как уже упоминалось в комментариях))))

Ответы [ 2 ]

0 голосов
/ 12 февраля 2019

Вы можете создать Predicate<LocationVO поэтапно:

    Predicate<LocationVO> p = l -> true;
    if (filter.getClient_id() != null) {
        p = p.and(l -> filter.getClient_id().longValue() !=  l.getParent_client_id());
    }
    if (filter.getLocation_id() != null) {
        p = p.and(l -> l.getLocation_id().longValue() == filter.getLocation_id());
    }
    if (filter.getLocation_type() != null) {
        p = p.and(l -> filter.getLocation_type().equals(l.getLocation_type()));
    }

и затем использовать встроенный предикат для фильтрации потока:

    List<LocationVO> listLocation = listLocationAll.stream()
            .filter(p)
            .collect(Collectors.toList());

Теперь, если вы переместите предикатесли учесть класс filter s, он выглядит еще лучше:

    // within the class of "filter"
    Predicate<LocationVO> createLocationVOPredicate() {
        Predicate<LocationVO> p = l -> true;
        if (getClient_id() != null) {
            p = p.and(l -> getClient_id().longValue() ==  l.getParent_client_id());
        }
        if (getLocation_id() != null) {
            p = p.and(l -> l.getLocation_id().longValue() == getLocation_id());
        }
        if (getLocation_type() != null) {
            p = p.and(l -> getLocation_type().equals(l.getLocation_type()));
        }
        return p;
    }

и использование:

    listLocation = listLocationAll.stream()
            .filter(filter.createLocationVOPredicate())
            .collect(Collectors.toList());
0 голосов
/ 11 февраля 2019

Предполагая, что остальная логика будет иметь последовательную проверку каждого атрибута для добавления к условию фильтрации.Вы можете переместить такую ​​логику в реализацию equals (вместе с hashCode) внутри самого объекта, а затем снова использовать более простой потоковый конвейер, как:

List<LocationVO> filterList(List<LocationVO> input, LocationVO elem) {
    return input.stream()
        .filter(o -> elem.equals(o))
        .collect(Collectors.toList());
}
...