J'ai une carte Map<K, V>
et mon objectif est de supprimer les valeurs dupliquées et de reproduire la même structure Map<K, V>
. Dans le cas où la valeur dupliquée est trouvée, il faut sélectionner une clé ( k
) parmi les deux clés ( k1
et k1
) qui contiennent ces valeurs, pour cette raison, supposons que le BinaryOperator<K>
don k
de k1
et k2
est disponible.
Exemple d'entrée et de sortie:
// Input
Map<Integer, String> map = new HashMap<>();
map.put(1, "apple");
map.put(5, "apple");
map.put(4, "orange");
map.put(3, "apple");
map.put(2, "orange");
// Output: {5=apple, 4=orange} // the key is the largest possible
Ma tentative d'utilisation Stream::collect(Supplier, BiConsumer, BiConsumer)
est un peu maladroite et contient des opérations mutables telles que Map::put
et Map::remove
que j'aimerais éviter:
// // the key is the largest integer possible (following the example above)
final BinaryOperator<K> reducingKeysBinaryOperator = (k1, k2) -> k1 > k2 ? k1 : k2;
Map<K, V> distinctValuesMap = map.entrySet().stream().collect(
HashMap::new, // A new map to return (supplier)
(map, entry) -> { // Accumulator
final K key = entry.getKey();
final V value = entry.getValue();
final Entry<K, V> editedEntry = Optional.of(map) // New edited Value
.filter(HashMap::isEmpty)
.map(m -> new SimpleEntry<>(key, value)) // If a first entry, use it
.orElseGet(() -> map.entrySet() // otherwise check for a duplicate
.stream()
.filter(e -> value.equals(e.getValue()))
.findFirst()
.map(e -> new SimpleEntry<>( // .. if found, replace
reducingKeysBinaryOperator.apply(e.getKey(), key),
map.remove(e.getKey())))
.orElse(new SimpleEntry<>(key, value))); // .. or else leave
map.put(editedEntry.getKey(), editedEntry.getValue()); // put it to the map
},
(m1, m2) -> {} // Combiner
);
Existe-t-il une solution utilisant une combinaison appropriée de l' Collectors
intérieur d'un Stream::collect
appel (par exemple sans opérations mutables)?
java
dictionary
java-8
java-stream
collectors
Nikolas
la source
la source
Stream
s?Map::put
ouMap::remove
dans leCollector
.BiMap
. Peut-être un doublon de Supprimer les valeurs en double de HashMap en JavaRéponses:
Vous pouvez utiliser Collectors.toMap
la source
Essayez ceci: de manière simple, inversez la clé et la valeur, puis utilisez le
toMap()
collecteur avec la fonction de fusion.la source
map
opération intermédiaire achète. Vous semblez échanger des clés et des valeurs, c'est clair, mais quel est le point, vous pourriez faire cela à l'étape de collecte tout de même?swap(); collect(key, value, binOp);
au lieu decollect(value, key, binOp)
. Peut-être que je dois essayer ça en vrai pour de vrai?Je trouve la solution non-streams plus expressive:
Ceci utilise
Map.merge
avec votre bi-fonction réductrice et utiliseLinkedHashMap
pour conserver l'ordre des entrées d'origine.la source
J'ai trouvé un moyen d'utiliser uniquement
Collectors
sans avoir besoin de collecter et de traiter à nouveau la carte retournée. L'idée est:Groupe le
Map<K, V>
àMap<V, List<K>
.Réduisez les nouvelles clés (
List<K>
) à l'K
utilisationBinaryOperator<K>
.Inversez à
Map<V, K>
nouveau le retour à laMap<K, V>
structure - ce qui est sûr car les clés et les valeurs sont garanties comme distinctes.Le code final:
la source
Une autre approche pour obtenir le résultat souhaité avec "Stream and Collectors.groupingBy".
la source