有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java收集器。使用相同的键映射(打印相同的键)

我有以下代码来获取地图:

List<MyObject> myList = myMethod.getList();
myList.stream().collect(
    Collectors.toMap(
        MyObject::getKey, 
        MyObject::getValue,
        (e1, e2) -> {
            System.out.println("Duplicate keys !!!");
            return e1;
        }, 
        LinkedHashMap::new
    )
);

如何使用重复密钥打印消息“重复密钥”


共 (2) 个答案

  1. # 1 楼答案

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

    使用当前代码,您将获得消息“Duplicate keys”,其中包含一个MyObject列表,其中至少包含两个MyObject实例,这些实例的对象与getKey()的值相等,例如Arrays.asList(new MyObject("foo", "bar"), new MyObject("foo", "bar2"))

    How to get the corresponding key?

    到目前为止,不可能获得相应的键,您当前从merge函数中获得的实际上是使用同一键映射的2个值,这些值需要合并,以便为相应的键只保留一个值

    您的问题是一个已知的问题,已在Java9中修复,请参见JDK-8040892。有关更多详细信息,相应的修复将允许我们从merge函数获取要合并的键和值

    另见Why does Collectors.toMap report value instead of key on Duplicate Key error?

  2. # 2 楼答案

    正如在this answer中所解释的,这是一个已知的问题,将在Java 9中得到解决,至少对于不接受合并函数的toMap收集器来说是这样

    由于merge函数只接收要合并的两个值,并且签名不容易更改,因此这些重载方法目前还没有解决方案。不幸的是,没有toMap收集器在没有显式合并函数的情况下接受Map{},因此,除非在发布之前更改,否则将无法修复应返回LinkedHashMap的场景

    因此,解决方案是实现您自己的收集器。然后,您不必等待Java9,也不必冒着失望的风险

    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));
    }
    

    您可以将此收集器用作

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

    或者使用限定的MyCollector.toMap,引用放置该自定义收集器的类