繁体   English   中英

Java 8 Hashmap 内部结构

[英]Java 8 Hashmap Internals

我已经完成了 Java 8 Hashmap 的实现,并带着以下疑问来到这里。 请帮我澄清一下:

  1. 我在一篇文章中读到,具有相同哈希码的节点将被添加到与链表相同的存储桶中。 它说这个链表的新节点将被添加到头部而不是尾部以避免尾部遍历。 但是当我看到源代码时,新节点被添加到尾部。 那是对的吗?
  2. 我没有完全理解这个变量 MIN_TREEIFY_CAPACITY。 是不是经过这么多计数,整个地图将被转换为树(从数组到树)?

但是当我看到源代码时,新节点被添加到尾部。 那是对的吗?

在旧版本中,它被添加到头部。 但是,在 Java 8 中进行了许多更改。

class A {
    static class SameHash {
        final int n;

        SameHash(int n) {
            this.n = n;
        }

        @Override
        public int hashCode() {
            return 1;
        }

        @Override
        public String toString() {
            return "SameHash{" +
                    "n=" + n +
                    '}';
        }
    }

    public static void main(String[] args) {
        HashSet<SameHash> set = new HashSet<>();
        for (int i = 1; i <= 4; i++)
            set.add(new SameHash(i));
        System.out.println(set);
    }
}

印刷

[SameHash{n=1}, SameHash{n=2}, SameHash{n=3}, SameHash{n=4}]

注意:键可以有不同的哈希码,但最终可以在同一个存储桶中。

我没有完全理解这个变量 MIN_TREEIFY_CAPACITY。 是不是经过这么多计数,整个地图将被转换为树(从数组到树)?

在此计数之后,如果键为Comparable ,则桶将转换为树

Peter Lawrey 对 MIN_TREEIFY_CAPACITY 的回应是错误的。

此常量默认为 64,并在 java.util.HashMap#treeifyBin 方法中使用,如果存储桶的大小大于 8 (TREEIFY_THRESHOLD),则会调用该方法。

在 java.util.HashMap#treeifyBin 方法中,如果哈希表大小小于 64,则整个表被 RESIZED - 加倍,否则,所讨论的桶是 TREEIFIED - 桶的 DS - 链表被转换为二叉树。

重点是保持 O(1) 插入或查找 - 如果哈希表大小很小(64),我们可以通过加倍轻松调整它的大小,因此存储桶的范围将加倍,并且哈希冲突会更少钥匙和每个桶将有更少的项目。

如果表大小大于 64,那么将哈希表大小加倍可能会很昂贵,最好只是将当前存储桶的链表转换为搜索速度更快的二叉树存储桶(链表搜索是 O(n ) 而二叉树搜索是 O(log(n))。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM