如果过滤条件是多个且动态发生,则从列表中过滤对象

时间:2017-08-15 13:57:36

标签: java java-8

我有一个要求,我必须根据多个动态过滤条件从列表中过滤对象。

我已经通过循环遍历对象编写代码,然后全部过滤并在任何条件不匹配时返回false。我写的代码是

    Map<String, String> obj1  = new HashMap<>();
    obj1.put("id", "1");
    obj1.put("name", "name1");
    obj1.put("dept", "IT");
    obj1.put("sex", "M");

    Map<String, String> obj2  = new HashMap<>();
    obj2.put("id", "2");
    obj2.put("name", "name2");
    obj2.put("dept", "IT");
    obj2.put("sex", "M");

    Map<String, String> obj3 = new HashMap<>();
    obj3.put("id", "3");
    obj3.put("name", "name3");
    obj3.put("dept", "DEV");
    obj3.put("sex", "F");

    ArrayList<Map<String, String>> employees = new ArrayList<>(Arrays.asList(obj1,obj2,obj3));

    Map<String, String> filterCondition = new HashMap<>();
    filterCondition.put("dept", "IT");
    filterCondition.put("sex", "M");

    List<Map<String, String>> filteredEmployee = new ArrayList<>();

    for(Map<String,String> employee:employees){
        if(isValid(filterCondition, employee)){
            filteredEmployee.add(employee);
        }
    }

    System.out.println(filteredEmployee);

isValid方法是

private static boolean isValid(Map<String, String> filterCondition, Map<String, String> employee) {
    for(Entry<String, String> filterEntry:filterCondition.entrySet()){
        if(!employee.get(filterEntry.getKey()).equals(filterEntry.getValue())){
            return false;
        }
    }
    return true;
}

如果我得到的过滤器是动态的,那么有没有更好的方法来实现它。

我已经在stackoverflow中看到了here的一些答案,但没有帮助

2 个答案:

答案 0 :(得分:3)

将所有过滤器组合为单个谓词(使用stream,reduce和谓词组合):

Predicate<Map<String, String>> allConditions = filterCondition
        .entrySet()
        .stream()
        .map(ThisClass::getAsPredicate)
        .reduce((employee) -> true, Predicate::and);

然后只使用Stream.filter()

List<Map<String, String>> filteredEmployees = employees
        .stream()
        .filter(allConditions)
        .collect(Collectors.toList());

辅助功能:

private static Predicate<Map<String, String>> getAsPredicate(Map.Entry<String, String> filter) {
    return (Map<String, String> employee) -> employee.get(filter.getKey()).equals(filter.getValue());
}

答案 1 :(得分:2)

也许你可以在Stream中使用for循环:

    Stream<Map<String, String>> employeeStream = employees.stream();
    for (Map.Entry<String, String> entry : filterCondition.entrySet()) {
        employeeStream = employeeStream.filter(map -> entry.getValue()
                                          .equals(map.get(entry.getKey())));
    }
    List<Map<String, String>> filteredEmployee = employeeStream.collect(Collectors.toList());