java - HashMap 中的 keySet() 方法可能更简洁

标签 java java-8 hashmap keyset

这个问题在这里已经有了答案:





Why is the local variable ks declared in the HashMap.keySet()? [duplicate]

(2 个回答)


10 个月前关闭。




Mac OS 上的 JDK 8,查看 HashMap.java 中的以下代码:

    public Set<K> keySet() {
        Set<K> ks = keySet;
        if (ks == null) {
            ks = new KeySet();
            keySet = ks;
        }
        return ks;
    }
对返回的 ks 的任何更改都将反射(reflect)在 keySet 中,因为它们始终指向相同的底层集合,如果这是真的,可以写成:
    public Set<K> keySet() {
        if (keySet == null) {
            keySet = new KeySet();
        }
        return keySet;
    }
两个代码片段的行为是否相同?
如果是,为什么HashMap使用第一个变体而不是第二个变体?

最佳答案

缓存到局部变量是为了提高性能。生成的字节码更小,该字段被读取一次,因此缓存未命中可能只发生一次,以及其他一些事情。
这是一项非常高级的优化,应该只在非常频繁运行的代码段上进行。它被应用在这里的原因,可能是因为 HashMap是用 Java 1.2 编写的,当时 JIT 是非常基础的,因此类似的东西产生了相当大的影响。
在这种情况下,也是为了支持多线程访问而做的。HashMap不同步,但是如果以后没有修改它可以通过安全发布共享。如果两个线程同时执行该方法,则可能会出现竞争条件:if(keySet == null) 中的第一次读取可以读取另一个线程写入的较新值,第二次读取 return keySet;读取较旧的 ( null ) 值。使用局部变量确保 ifreturn非空时使用相同的引用。所以它永远无法返回 null .

关于java - HashMap 中的 keySet() 方法可能更简洁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64923690/

相关文章:

java - Spring Boot 2 没有序列化 LocalDateTime

java - 创建的 Runnables 的 lambda 的不同行为

java - Java 流中的 "escape-hatch operation"是什么?

java - 在 Java 中对流应用过滤器

python - Python dicts 如何保持按键顺序

java - 在矩阵java中找到相等数字的最大区域

java - 导入自定义包显示 "error: package com does not exist"

java - 如何从非 Activity 类实例化 Activity 类的对象?

java - 更新存储迭代器时的ConcurrentModificationException(用于LRU缓存实现)

Java - 在重载的构造函数调用中创建 HashMap