如何让ComputeIfPresent在Map中使用Map?

时间:2018-04-23 11:52:40

标签: java dictionary hashmap

当尝试使用 computeIfPresent()方法更改Map时,我在使用innerMap时无法实现此方法。

这有效:

Map<String, Integer> mapOne = new HashMap<>();
mapOne.computeIfPresent(key, (k, v) -> v + 1);

这不起作用:

Map<String, Map<String, Integer>> mapTwo = new HashMap<>();
mapTwo.computeIfPresent(key, (k, v) -> v.computeIfPresent(anotherKey, (x, y) -> y + 1);

在第二个示例中,我收到以下错误消息:“lambda表达式中的错误返回类型:整数无法转换为Map<String, Integer>”。 我的IDE将v识别为Map。但是这个功能不起作用。

显然该方法返回一个Integer,但是我没有看到它与第一个没有Innermap的方法的区别。到目前为止,我还没有在网上找到类似的案例。

我怎样才能让它发挥作用?

3 个答案:

答案 0 :(得分:9)

外部lambda表达式应返回Map引用的v

mapTwo.computeIfPresent(key, 
                        (k, v) -> {
                                v.computeIfPresent(anotherKey, (x, y) -> y + 1); 
                                return v;
                            });

它无法返回表达式Integer的{​​{1}}值。

答案 1 :(得分:8)

为了解你的问题,让我们来看看你正在使用的方法的签名:

.container:hover a.one, .container:hover a.two { color: blue; }

如您所见,它返回一个基于V computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)泛型参数的类型,该参数代表存储在V中的值。这是您遇到问题的地方:您的内部地图会存储Map,因此当您致电Integer时,您获得computeIfPresent,而外部地图需要另一个Integer

修改
写作的时候,我意识到Eran已经给出了一个代码示例,说明了如何做到这一点 但是我会留下这个答案,因为它解释了为什么你的方法不起作用,所以它可能对某人有帮助。

答案 2 :(得分:0)

稍微偏离主题(某种程度上),但为相同的地图做同样的事情,以神秘的方式打破:

// breaks with ConcurrentModificationException
Map<String, Integer> test = new HashMap<>(); // or  = new Hashtable<>();
test.computeIfAbsent("one", x -> test.computeIfAbsent("one", y -> 1));

// IllegalStateException: Recursive update
Map<String, Integer> test = new ConcurrentHashMap<>();
// ... same code

// the only one that works correctly that I am aware of
Map<String, Integer> test = new ConcurrentSkipListMap<>();