【问题标题】:Which tree type used in java 8 HashMap bucket?java 8 HashMap 存储桶中使用了哪种树类型?
【发布时间】:2017-05-10 18:39:08
【问题描述】:

据我所知,java8 HashMap 存储桶的实现有所改变。如果桶大小超过某个值,则列表转换为“平衡树”。

我不明白
1. Oracle JDK 使用什么类型的平衡树? (AVL?红黑?类似于数据库中的索引?)
2. 是二叉树吗?
3. 据我了解,排序是根据哈希码执行的。例如,在我的存储桶中,我有 102 个元素。 100 个值,哈希码等于 12(我知道它值得,但我只需要了解这种行为)和 2 个哈希码 22。
值如何执行搜索?

【问题讨论】:

  • 请注意,您不应依赖此行为。这是一个特定于实现的回退,以防代码已经出现错误行为(集群哈希码)。如果你的键没有很好地散列但具有可比性,你也可以从一开始就使用树形图。

标签: java hashmap java-8


【解决方案1】:

查看实现,它看起来像一棵二叉树。更具体地说,下面的评论表明它是一棵红黑树:

static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
    TreeNode<K,V> parent;  // red-black tree links
    TreeNode<K,V> left;
    TreeNode<K,V> right;
    TreeNode<K,V> prev;    // needed to unlink next upon deletion
    boolean red;
    ...
}

关于处理相等的哈希码,这在 Javadoc 中有说明:

树箱(即元素都是 TreeNodes 的箱)是 主要按 hashCode 排序,但在平局的情况下,如果两个 元素是相同的“class C implements Comparable&lt;C&gt;”, type 然后他们的 compareTo 方法用于排序。

据说HashMap 中使用的TreeNodes 的结构类似于TreeMap

您可以在此处查看搜索包含所需密钥的TreeNode 的实现:

    /**
     * Finds the node starting at root p with the given hash and key.
     * The kc argument caches comparableClassFor(key) upon first use
     * comparing keys.
     */
    final TreeNode<K,V> find(int h, Object k, Class<?> kc) {
        TreeNode<K,V> p = this;
        do {
            int ph, dir; K pk;
            TreeNode<K,V> pl = p.left, pr = p.right, q;
            if ((ph = p.hash) > h)
                p = pl;
            else if (ph < h)
                p = pr;
            else if ((pk = p.key) == k || (k != null && k.equals(pk)))
                return p;
            else if (pl == null)
                p = pr;
            else if (pr == null)
                p = pl;
            else if ((kc != null ||
                      (kc = comparableClassFor(k)) != null) &&
                     (dir = compareComparables(kc, k, pk)) != 0)
                p = (dir < 0) ? pl : pr;
            else if ((q = pr.find(h, k, kc)) != null)
                return q;
            else
                p = pl;
        } while (p != null);
        return null;
    }

如您所见,这类似于标准的二叉搜索树搜索。首先,他们搜索具有与搜索键相同的hashCodeTreeNode(因为HashMap 的单个桶可能包含具有不同hashCodes 的条目)。然后它继续直到找到具有等于所需密钥的密钥的TreeNode。如果键的类实现Comparable,则辅助搜索使用compareTo。否则,将执行更详尽的搜索。

【讨论】:

  • 但是如果 compareTo 没有实现呢?
  • 如果 JDK 已经有了 TreeMap,那为什么要用另一个名字创建同一个类呢?
  • @gstackoverflow 不是同一个类。 HashMap 中使用的TreeNode 是一个实现细节。当单个 bin 中的条目数超过某个阈值时,它应该比 HashMap 的单个 bin 的原始链表实现提供更好的性能。
  • 我明白这一点。我的问题有点不同。为什么jdk创始人不能在HashMap里面使用TreeMap而不是TreNode?​​span>
  • @gstackoverflow 可以自己看代码。有一个find(int h, Object k, Class&lt;?&gt; kc) 方法查找具有传递的hashCode (h) 并且其键等于k 的TreeNode。如果它到达一个哈希码是所需值但键不相等的 TreeNode,它要么使用 compareTo(如果可用)或在右子树中递归搜索键,如果找不到则在左子树中搜索。
猜你喜欢
  • 2015-01-08
  • 2011-06-06
  • 1970-01-01
  • 1970-01-01
  • 2016-10-14
  • 2017-05-09
  • 1970-01-01
  • 2018-06-10
  • 1970-01-01
相关资源
最近更新 更多