如何简化.filter主体中的巨大if语句?

时间:2019-02-11 17:25:04

标签: java if-statement filter java-8 java-stream

有没有更好的意思,更具可读性的表达方式?

    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包含

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语句: 如果为客户端ID设置了过滤器->不包含任何与其关联的客户端没有此ID的LocationVO

第二个if语句: 如果为位置设置了过滤器->删除/过滤所有没有此ID的LocationVO

第三个if语句: 过滤所有没有过滤器的location_type的VO。

(((我想,没有一个是过时的((正如评论中提到的))))

2 个答案:

答案 0 :(得分:2)

您可以分阶段构建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的类中,它看起来会更好:

    // 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());

答案 1 :(得分:1)

假设逻辑的其余部分将对每个属性进行顺序检查以添加到过滤条件中。您可以将这种逻辑移至对象本身内的equals(以及hashCode)实现中,然后再次使用更简单的流管道,如下所示:

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