感觉 Lambda 加上递归调用,就有点搞不懂运行过程了

2020-07-19 13:05:13 +08:00
 amiwrong123

https://bugs.openjdk.java.net/browse/JDK-8240162

这个 ConcurrentHashMap 的 bug,运行它的用例,会产生一个 bug,就是明明 map 中有映射,但 size 为 0 。

import java.util.concurrent.*;

public class test5 {
    public static void main(String[] args) {

        final ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();

        final String key = "key";
        final String value = "value";

        map.put("anotherKey", "anotherValue");
        map.put(key, value);

        System.out.println("size=" + map.size());

        map.computeIfPresent(key, (aKey, aValue) -> {
            map.computeIfPresent(key, (bKey, bValue) -> null);
            return null;
        });

        System.out.println("size=" + map.size());//这句返回 0
        map.put(key, value);//这句打断点
        System.out.println("size=" + map.size());
    }
}

可以发现明明 map 中有映射,但 size 为 0 。

  1. 为什么没有产生无限递归,看起来会无限递归啊?感觉调用过程好难理解
  2. 为啥执行完,size 返回错误的值?

运行环境 jdk8

2265 次点击
所在节点    Java
5 条回复
amiwrong123
2020-07-19 14:07:40 +08:00
好吧,看错了,不会产生无限递归,不过咋一看这个过程确实有点搞不清楚
312ybj
2020-07-19 15:30:34 +08:00
你可以尝试改变 debug 的类型,右击一下短点
yanshenxian
2020-07-19 17:09:32 +08:00
ConcurrentHashMap 的 size 方法本来就是不精确的
这个例子也没有递归操作啊 computeIfPresent 里的 lambda 返回空相当于 remove 这个 key 了,内部操作 count -1
这就相当于操作了两次 -1 最后计算的 size 就是 0

如果换成 HashMap 这里就会抛出 ConcurrentModificationException
no1xsyzy
2020-07-20 13:24:38 +08:00
没有哪个函数调用了自身,只是存在某处回调中再次调用同样的外部函数,你可能把它误看作是的递归了。
amiwrong123
2020-07-20 19:33:00 +08:00
@no1xsyzy
是的,并不是递归

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/691318

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX