java - How to produce map with distinct values from a map (and use the right key using BinaryOperator)?
问题描述
I have a map Map<K, V>
and my goal is to remove the duplicated values and output the very same structure Map<K, V>
again. In case the duplicated value is found, there must be selected one key (k
) from the two keys (k1
and k2
) which hold these values, for this reason, assume the BinaryOperator<K>
giving k
from k1
and k2
is available.
Example input and output:
// 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
My attempt using Stream::collect(Supplier, BiConsumer, BiConsumer)
is a bit very clumsy and contains mutable operations such as Map::put
and Map::remove
which I would like to avoid:
// // 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
);
Is there a solution using an appropriate combination of Collectors
within one Stream::collect
call (e.g. without mutable operations)?
解决方案
您可以使用Collectors.toMap
private Map<Integer, String> deduplicateValues(Map<Integer, String> map) {
Map<String, Integer> inverse = map.entrySet().stream().collect(toMap(
Map.Entry::getValue,
Map.Entry::getKey,
Math::max) // take the highest key on duplicate values
);
return inverse.entrySet().stream().collect(toMap(Map.Entry::getValue, Map.Entry::getKey));
}
推荐阅读
- python - 即使定义了函数也没有定义?Python的简单哈希实现
- sql - 将单独列中的分类数据合并为具有类别指示符的单个列
- wordpress - 子/子类别中的 ACF 字段
- r - 如何在 R 中使用 for 循环将数据绘制为箱线图网格(4x3)?
- macos - 将文件意外移动到新文件夹后,有没有办法将文件移回原来的位置?
- visual-studio - Visual Studio 中的“同步命名空间”功能有什么作用?
- python - 在列表中附加列表有一些问题
- java - WSL 上的 Intellij IDEA 调试
- python - 希望将“selected_song_obj”的新值重新分配给所有等效的 ObjectProperties
- java - 如果请求带有相同的参数,如何从缓存返回响应