Tengo un mapa Map<K, V>y mi objetivo es eliminar los valores duplicados y generar la misma estructura Map<K, V>nuevamente. En caso de que se encuentre el valor duplicado, debe seleccionarse una clave ( k) de las dos claves ( k1y k1) que contienen estos valores, por esta razón, asumir la BinaryOperator<K>entrega kde k1y k2está disponible.
Ejemplo de entrada y salida:
// 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
Mi intento de usar Stream::collect(Supplier, BiConsumer, BiConsumer)es un poco torpe y contiene operaciones mutables como Map::puty Map::removeque me gustaría evitar:
// // 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 una solución que use una combinación adecuada de Collectorsuna Stream::collectllamada (por ejemplo, sin operaciones mutables)? 
                    
                        java
                                dictionary
                                java-8
                                java-stream
                                collectors
                                
                    
                    
                        Nikolas
fuente
                
                fuente

Streams?Map::putoMap::removedentro deCollector.BiMap. Posiblemente un duplicado de Eliminar valores duplicados de HashMap en JavaRespuestas:
Puedes usar Collectors.toMap
fuente
Pruebe esto: la manera simple es invertir la clave y el valor y luego usar el
toMap()recopilador con la función de combinación.fuente
mapcompra la operación intermedia . Pareces intercambiar claves y valores, eso está claro, pero ¿cuál es el punto, podrías hacer eso en el paso de recopilación de la misma manera?swap(); collect(key, value, binOp);lugar de hacerlocollect(value, key, binOp). ¿Quizás necesito probar esto en un jshell de verdad?Encuentro que la solución no streams es más expresiva:
Esto se usa
Map.mergecon su bi-función reductora y se usaLinkedHashMappara preservar el orden de las entradas originales.fuente
Encontré una forma de usar solo
Collectorssin necesidad de recopilar y procesar nuevamente el Mapa devuelto. La idea es:Agrupa el
Map<K, V>aMap<V, List<K>.Reduzca las nuevas teclas (
List<K>) paraKusarBinaryOperator<K>.Invierta la parte
Map<V, K>posterior a laMap<K, V>estructura nuevamente, lo cual es seguro ya que tanto las claves como los valores están garantizados como distintos.El código final:
fuente
Otra aproximación para obtener el resultado deseado con "Stream and Collectors.groupingBy".
fuente