У меня есть карта, Map<K, V>
и моя цель состоит в том, чтобы удалить дублированные значения и Map<K, V>
снова вывести ту же структуру . В случае дублируется значение найдено, то необходимо выбрать один ключ ( k
) из двух клавиш ( k1
и k1
) , которые держат эти ценности, по этой причине, предположим , что BinaryOperator<K>
дает k
от k1
и k2
доступно.
Пример ввода и вывода:
// 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
Моя попытка использования Stream::collect(Supplier, BiConsumer, BiConsumer)
является немного очень неуклюжа и содержит изменяемые такие операции, как Map::put
и Map::remove
которые я хотел бы избежать:
// // 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
);
Есть ли решение, использующее подходящую комбинацию Collectors
внутри одного Stream::collect
вызова (например, без изменяемых операций)?
java
dictionary
java-8
java-stream
collectors
Nikolas
источник
источник
Stream
s?Map::put
или вMap::remove
пределахCollector
.BiMap
. Возможно дубликат Удалить дубликаты значений из HashMap в JavaОтветы:
Вы можете использовать Collectors.toMap
источник
Попробуйте это: простой способ инвертировать ключ и значение, затем использовать
toMap()
коллектор с функцией слияния.источник
map
покупает промежуточная операция. Кажется, вы меняете ключи и значения, это понятно, но какой смысл, вы могли бы сделать это на этапе сбора?swap(); collect(key, value, binOp);
вместоcollect(value, key, binOp)
. Может быть, мне нужно попробовать это в jshell по-настоящему?Я нахожу решение, не относящееся к потокам, более выразительным:
Это используется
Map.merge
с вашей двойной би-функцией и используетсяLinkedHashMap
для сохранения исходного порядка записей.источник
Я нашел способ использования только
Collectors
без необходимости повторного сбора и дальнейшей обработки возвращенной Карты. Идея заключается в следующем:Сгруппировать
Map<K, V>
вMap<V, List<K>
.Уменьшите новые ключи (
List<K>
) дляK
использованияBinaryOperator<K>
.Инвертировать
Map<V, K>
обратно кMap<K, V>
структуре снова - который является безопасным , так как ключи и значения гарантируются различными.Финальный код:
источник
Другой подход, чтобы получить желаемый результат с «Stream and Collectors.groupingBy».
источник