In den meisten Fällen sollten Sie bei der Verwendung von forEach
in einem Stream überdenken, ob Sie das richtige Tool für Ihren Job verwenden oder ob Sie es richtig verwenden.
Im Allgemeinen sollten Sie nach einer geeigneten Terminaloperation suchen, die das erreicht, was Sie erreichen möchten, oder für einen geeigneten Collector. Jetzt gibt es Collectors für die Produktion von Map
s und List
s, aber kein Out-of-the-Box-Kollektor für die Kombination von zwei verschiedenen Kollektoren, basierend auf einem Prädikat.
Jetzt enthält this answer einen Kollektor zum Kombinieren zweier Kollektoren. Mit diesem Kollektor, können Sie die Aufgabe als
Pair<Map<KeyType, Animal>, List<KeyType>> pair = animalMap.entrySet().stream()
.collect(conditional(entry -> entry.getValue() != null,
Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue),
Collectors.mapping(Map.Entry::getKey, Collectors.toList())));
Map<KeyType,Animal> myMap = pair.a;
List<KeyType> myList = pair.b;
erreichen Aber vielleicht können Sie diese spezielle Aufgabe auf einfachere Art und Weise lösen. Eines Ihrer Ergebnisse entspricht dem Eingabetyp. Es ist die gleiche Karte, die nur die Einträge entfernt, die auf null
abgebildet sind.Wenn Ihre ursprüngliche Karte wandelbar ist und Sie es danach nicht mehr benötigen, können Sie nur die Liste sammeln und diese Schlüssel aus der Original-Karte entfernen, da sie sich gegenseitig ausschließen:
List<KeyType> myList=animalMap.entrySet().stream()
.filter(pair -> pair.getValue() == null)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
animalMap.keySet().removeAll(myList);
Beachten Sie, dass Zuordnungen zu null
entfernen auch ohne die Liste der anderen Tasten mit:
animalMap.values().removeIf(Objects::isNull);
oder
animalMap.values().removeAll(Collections.singleton(null));
Wenn Sie die ursprüngliche Karte nicht ändern können (oder möchten), gibt es immer noch eine Lösung ohne einen benutzerdefinierten Kollektor. Wie in Alexis C.’s answer angedeutet, partitioningBy
in die richtige Richtung geht, aber man kann es vereinfachen:
Map<Boolean,Map<KeyType,Animal>> tmp = animalMap.entrySet().stream()
.collect(Collectors.partitioningBy(pair -> pair.getValue() != null,
Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)));
Map<KeyType,Animal> myMap = tmp.get(true);
List<KeyType> myList = new ArrayList<>(tmp.get(false).keySet());
Unterm Strich ist, nicht über gewöhnliche Sammlung Operationen vergessen, müssen Sie nicht alles, was mit dem tun, neue Stream-API
Scheint wie eine Situation, in der Ströme nicht wirklich tun Sie irgendwelche Gefälligkeiten. Es versteckt nur die Kontrollfluss-Syntax mit API in einer Weise, die sich als unangenehm herausstellt und Ihr forEach-Lambda statusbehaftet ist. – Radiodef