2017-08-15 21 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としてstackoverflowの中にいくつかの答えを見てきましたが、無助けを借りて

+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

関連する問題