2017-03-17 92 views
2

我有多個功能來篩選基於標準的對象的地圖。流和lambdas作爲參數

函數具有相同的主體,只有布爾傳遞條件會改變。

filterOnFirstCriteria(Criteria criterias, Map<Integer, List<Container>> containerMap, Map<Integer, ClassKey> classKeys) { 
     for (Map.Entry<Integer, List<Container>> entry : containerMap.entrySet()) { 
      List<Container> containers = entry.getValue(); 
      ClassKey classKey = classKeys.get(entry.getKey()); 
      for (Container container : containers) { 
       List<MyObject> found = new ArrayList<>(); 
       for (MyObject myObject : container.getMyObjects()) { 
        boolean pass = criterias.getListOfFilter().stream().filter(s -> s.equals(container.getReference())).count() > 0; 
        if (pass) { 
         found.add(myObject); 
        } 
       } 
       container.getMyObjects().removeAll(found); 
      } 
     } 
    } 


filterOnOtherCriteria(Criteria criterias, Map<Integer, List<Container>> containerMap, Map<Integer, ClassKey> classKeys) { 
     for (Map.Entry<Integer, List<Container>> entry : containerMap.entrySet()) { 
      List<Container> containers = entry.getValue(); 
      ClassKey classKey = classKeys.get(entry.getKey()); 
      for (Container container : containers) { 
       List<MyObject> found = new ArrayList<>(); 
       for (MyObject myObject : container.getMyObjects()) { 
        boolean pass = myObject.getListOfObject().stream().filter(obj -> criterias.getLocations().stream().anyMatch(location -> location.equals(obj.getLocation()))).count() > 0; 
        if (pass) { 
         found.add(myObject); 
        } 
       } 
       container.getMyObjects().removeAll(found); 
      } 
     } 
    } 

條件可以在來自上層環路的任何對象上。 我想將重複的循環代碼提取到一個函數中,但我不知道如何爲布爾條件傳遞某種回調。

謝謝。

+3

傳遞一個附加斷言,其中上下文將包含所有必要的信息,謂詞來決定它應該返回true或false(即myObject的,容器,標準S)。 –

回答

3

在這兩種方法的唯一區別是語句:

boolean pass = criterias.getListOfFilter().stream() 
    .filter(s -> s.equals(container.getReference())) 
    .count() > 0; 

boolean pass = myObject.getListOfObject().stream() 
    .filter(obj -> criterias.getLocations().stream() 
      .anyMatch(location -> location.equals(obj.getLocation()))) 
    .count() > 0; 

第一條語句不依賴於myObject從內循環,但對container獲取從外循環取。它也取決於傳遞給該方法的參數criterias

第二條語句取決於從內部循環取回的myObject以及傳遞給該方法的參數criterias

所以,如果你想重構出那些語句,即產生boolean,你必須要找到同時支持之類的語句統一的方法:

@FunctionalInterface 
public interface Guardian { 
    boolean pass(MyObject myObject, Container container); 
} 

現在,您可以提取這兩個報表,並通過他們你的新方法,lambda表達式:

public static void filterOnFirstCriteria(Criteria criterias, Map<Integer, List<Container>> containerMap, Map<Integer, ClassKey> classKeys) { 
    filterOn(criterias, containerMap, classKeys, (myObject, container) -> 
     criterias.getListOfFilter().stream() 
            .filter(s -> s.equals(container.getReference())) 
            .count() > 0); 
} 

public static void filterOnOtherCriteria(Criteria criterias, Map<Integer, List<Container>> containerMap, Map<Integer, ClassKey> classKeys) { 
    filterOn(criterias, containerMap, classKeys, (myObject, container) -> 
     myObject.getListOfObject().stream() 
            .filter(obj -> criterias.getLocations().stream().anyMatch(location -> location.equals(obj.getLocation()))) 
            .count() > 0); 
} 

public static void filterOn(Criteria criterias, Map<Integer, List<Container>> containerMap, Map<Integer, ClassKey> classKeys, Guardian guardian) { 
    for (Map.Entry<Integer, List<Container>> entry : containerMap.entrySet()) { 
     List<Container> containers = entry.getValue(); 
     ClassKey classKey = classKeys.get(entry.getKey()); 
     for (Container container : containers) { 
      List<MyObject> found = new ArrayList<>(); 
      for (MyObject myObject : container.getMyObjects()) { 
       if (guardian.pass(myObject, container)) { 
        found.add(myObject); 
       } 
      } 
      container.getMyObjects().removeAll(found); 
     } 
    } 
}