【问题标题】:Java 8 Hashmap InternalsJava 8 Hashmap 内部结构
【发布时间】:2019-12-10 23:29:04
【问题描述】:

我已经完成了 Java 8 Hashmap 的实现,并提出了以下疑问。请帮我澄清一下:

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

【问题讨论】:

    标签: java hashmap


    【解决方案1】:

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

    在旧版本中,它被添加到头部。但是,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}]
    

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

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

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

    【讨论】:

      【解决方案2】:

      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))。

      【讨论】:

      • 那么在表大小达到64,桶大小达到8之后,那么只有那个桶会被转换成树对吧?还是表中的所有桶?
      • 正确,只有达到阈值的桶才会从Node(链表)转换为TreeNode(平衡/二叉树)。请记住,从 TreeNode 到 Node 也存在反向转换,当哈希表调整大小以及一些大桶的大小变得小于 UNTREEIFY_THRESHOLD = 6 时会发生这种情况
      猜你喜欢
      • 2016-04-20
      • 1970-01-01
      • 2013-01-09
      • 1970-01-01
      • 1970-01-01
      • 2017-05-09
      • 2023-03-22
      • 1970-01-01
      • 2019-09-11
      相关资源
      最近更新 更多