2015-11-01 1 views
13

Ho una mappa in cui i valori sono stringhe e le chiavi sono elenchi: Map<String, List<BoMLine>> materials. Mi piacerebbe filtrare questa mappa con i suoi valori; qualcosa di simile:Come filtrare una mappa con i suoi valori in Java 8?

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

Ma non funziona per me. Qualcuno ha un'idea?

Grazie.

risposta

15

Se ho capito bene i criteri di filtro, si vuole verificare se il Stream filtrato hai prodotto dal valore List ha tutti gli elementi, e in caso affermativo, passare il corrispondente Map ingresso all'uscita 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())); 

Ciò presuppone MaterialDao.findMaterialByName(l.getMaterial()) restituisce un boolean.

+0

Non sono sicuro della mia soluzione e non funziona quando voglio raccoglierlo per mappare "e" non è t una mappa è solo un oggetto – Nazila

+1

@nazila 'e' è un' Map.Entry > '. Ho fatto alcuni errori di sintassi stupidi nella chiamata a 'raccogliere'. Vedi la risposta modificata. – Eran

+2

Non è necessario usare 'filter()', basta passare il predicato come argomento a 'anyMatch()'. –

0

infine ha reso il lavoro, la mia secondo filtro è stato completamente inutile, la risposta è in questo modo:

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

Se non hai più bisogno della mappa sorgente ed è modificabile, prova a eseguire l'operazione inplace: 'materials.values ​​(). RemoveIf (a ->! A.stream(). AllMatch (b -> MaterialDao.findMaterialByName (b .getMaterial()). isPresent())) ' – Holger

8

In genere, questo è come è possibile filtrare una mappa i suoi valori:

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)); 
} 

chiamata così:

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);