Collectors.toMap with same keys(print same key)

让人想犯罪 __ 提交于 2019-11-28 01:12:11
Nicolas Filotto

how i can print message "Duplicate keys" with duplicate key?

With your current code, you will get the message "Duplicate keys" with a list of MyObject which contains at least 2 instances of MyObject that have equal objects as value for getKey(), for example Arrays.asList(new MyObject("foo", "bar"), new MyObject("foo", "bar2")).

How to get the corresponding key?

Up to now it is not possible to get the corresponding key, what you currently get from the merge function are actually 2 values mapped with the same key that need to be merged to keep only one value for the corresponding key.

Your problem is a known issue that is fixed in Java 9 see JDK-8040892 for more details, the corresponding fix will allow us to get from the merge function both the key and the values to merge.

See Also Why does Collectors.toMap report value instead of key on Duplicate Key error?

Holger

As explained in this answer, this is a known issue that is going to be fixed in Java 9—at least for the toMap collector that doesn’t accept a merge function.

Since the merge function only receives the two values to be merged and signature can’t be easily changed, there is no fix for these overloaded methods in sight. Unfortunately, there is no toMap collector which accepts a Map Supplier without an explicit merge function, so unless this will change until the release, there will be no fix for your scenario where a LinkedHashMap should be returned.

So the solution is to implement your own collector. Then, you don’t have to wait for Java 9 and don’t risk to get disappointed.

static <T, K, V, M extends Map<K, V>> Collector<T, ?, M> toMap(
    Function<T, K> keyExtractor, Function<T, V> valueExtractor, Supplier<M> mapSupplier) {
    return Collector.of(mapSupplier,
        (m, t) -> putUnique(m, keyExtractor.apply(t), valueExtractor.apply(t)),
        (m1,m2)-> { m2.forEach((k, v) -> putUnique(m1, k, v)); return m1; }
    );
}
private static <K,V> void putUnique(Map<K,V> map, K key, V v1){
    V v2 = map.putIfAbsent(key, v1);
    if(v2 != null) throw new IllegalStateException(
        String.format("Duplicate key %s (values %s and %s)", key, v1, v2));
}

You can use this collector as

LinkedHashMap<KeyType, ValueType> map = myList.stream()
    .collect(toMap(MyObject::getKey, MyObject::getValue, LinkedHashMap::new));

or use a qualified MyCollector.toMap, referring to the class where you put that custom collector.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!