2015-11-01 99 views
13

我有一個地圖,其中的值是字符串,鍵是列表:Map<String, List<BoMLine>> materials。 我想按照其值來過濾此地圖;像這樣:如何通過在Java 8中的值來過濾映射?

materials.entrySet().stream() 
     .filter(a->a.getValue().stream() 
      .filter(l->MaterialDao.findMaterialByName(l.getMaterial()).ispresent) 

但它不適合我。有人有想法嗎?

謝謝。

回答

15

如果我理解正確的過濾條件,要檢查如果從價值List生產的過濾Stream有任何元素,如果是這樣,通過相應的Map進入輸出Map

Map<String, List<BoMLine>> 
    filtered = materials.entrySet() 
         .stream() 
         .filter(a->a.getValue() 
            .stream() 
            .anyMatch(l->MaterialDao.findMaterialByName(l.getMaterial()))) 
         .collect(Collectors.toMap(e->e.getKey(),e->e.getValue())); 

這是假設MaterialDao.findMaterialByName(l.getMaterial())返回boolean

+0

我不知道我的解決方案,它不工作時,我想收集它映射「e」是不t地圖它只是一個對象 – Nazila

+1

@nazila'e'是一個'Map.Entry >'。我在'collect'的調用中做了一些愚蠢的語法錯誤。見編輯的答案。 – Eran

+2

您不需要使用'filter()',只需將謂詞作爲參數傳遞給'anyMatch()'。 –

0

終於有了它的工作,我的第二個過濾器是完全無用的答案是這樣的:

Map<String, List<BoMLine>> 
filtered = materials.entrySet() 
        .stream() 
        .filter(a -> a 
         .getValue() 
         .stream() 
         .allMatch(
          b -> MaterialDao.findMaterialByName(
            b.getMaterial()).isPresent())) 
      .collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue())) 
+0

如果之後不需要源映射並且它是可變的,請考慮在位置執行操作:'material.values()。removeIf(a - >!a.stream()。allMatch(b - > MaterialDao.findMaterialByName(b .getMaterial())。isPresent()))' – Holger

8

一般來說,這是如何通過它的值進行過濾的地圖:

static <K, V> Map<K, V> filterByValue(Map<K, V> map, Predicate<V> predicate) { 
    return map.entrySet() 
      .stream() 
      .filter(entry -> predicate.test(entry.getValue())) 
      .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); 
} 

呼叫它是這樣的:

Map<String, Integer> originalMap = new HashMap<>(); 
originalMap.put("One", 1); 
originalMap.put("Two", 2); 
originalMap.put("Three", 3); 

Map<String, Integer> filteredMap = filterByValue(originalMap, value -> value == 2); 

Map<String, Integer> expectedMap = new HashMap<>(); 
expectedMap.put("Two", 2); 

assertEquals(expectedMap, filteredMap);