2015-11-01 62 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);