Mam mapę Map<K, V>
i moim celem jest usunięcie zduplikowanych wartości i Map<K, V>
ponowne wygenerowanie tej samej struktury . W przypadku, gdy wartość duplikatów zostanie znaleziony, musi być wybrany jeden klawisz ( k
) z dwóch przycisków ( k1
i k1
), które utrzymują te wartości, z tego powodu, przyjmijmy, że BinaryOperator<K>
dając k
od k1
i k2
jest dostępny.
Przykładowe dane wejściowe i wyjściowe:
// 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
Moja próba użycia Stream::collect(Supplier, BiConsumer, BiConsumer)
jest nieco niezręczna i zawiera zmienne operacje, takie jak Map::put
i Map::remove
których chciałbym uniknąć:
// // 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
);
Czy istnieje rozwiązanie wykorzystujące odpowiednią kombinację Collectors
jednego Stream::collect
połączenia (np. Bez operacji zmiennych)?
java
dictionary
java-8
java-stream
collectors
Nikolas
źródło
źródło
Stream
s?Map::put
lubMap::remove
wewnątrzCollector
.BiMap
. Prawdopodobnie duplikat Usuń zduplikowane wartości z HashMap w JavieOdpowiedzi:
Możesz użyć Collectors.toMap
źródło
Spróbuj tego: Prostym sposobem jest odwrócenie klucza i wartości, a następnie użycie
toMap()
kolektora z funkcją scalania.źródło
map
kupuje operacja pośrednia . Wydaje się, że zamieniasz klucze i wartości, to wszystko jest jasne, ale o co chodzi, możesz to zrobić na etapie zbierania tak samo?swap(); collect(key, value, binOp);
zamiastcollect(value, key, binOp)
. Może naprawdę muszę spróbować tego w jshell?Uważam, że rozwiązanie inne niż strumieniowe jest bardziej wyraziste:
To stosuje się
Map.merge
z twoją dwufunkcyjną redukcją i służyLinkedHashMap
do zachowania oryginalnej kolejności wpisów.źródło
Znalazłem sposób korzystania tylko
Collectors
bez potrzeby zbierania i dalszego przetwarzania zwróconej mapy. Chodzi o to:Grupuj
Map<K, V>
doMap<V, List<K>
.Zmniejsz liczbę nowych klawiszy (
List<K>
) doK
używaniaBinaryOperator<K>
.Z
Map<V, K>
powrotem odwróćMap<K, V>
strukturę do tyłu - co jest bezpieczne, ponieważ zarówno klucze, jak i wartości są gwarantowane jako odrębne.Ostateczny kod:
źródło
Kolejna próba uzyskania pożądanego rezultatu za pomocą „Stream and Collectors.groupingBy”.
źródło