2017-08-15 44 views
1

我有一個要求,即必須根據多個動態過濾器條件從列表中過濾對象。如果過濾器條件是多個且動態過濾,則從列表中過濾對象

我已經通過遍歷對象編寫了代碼,然後全部過濾,並在任何條件不匹配時返回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; 
} 

有沒有更好的方式來實現它,如果是我收到的過濾器是動態的到來。

我已經看到了計算器爲here一些答案,但沒有幫助

+0

你使用Java 8? – AjahnCharles

+0

我可以使用它。但即使使用流過濾器,我也無法更好地認爲解決方案。 – Roshan

+0

不是一個解決方案,但我會切換條件以避免潛在的NPE:if(!filterEntry.getValue()。equals(employee.get(filterEntry.getKey())))' –

回答

3

將所有過濾器作爲一個單一的謂詞(使用流,減少和謂語成分):

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

感謝這個美麗的答案。 – Roshan

2

也許你可以使用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()); 
+0

謝謝,這真的很有幫助。好方法 – Roshan

+0

@Roshan檢查CodeConfident的答案 - 它更清潔 –

+0

@Xiaff - 我其實也很喜歡讀你的;這是我不會想到的一種風格(你擴大了我的編程思想!) – AjahnCharles