java - HashMap 何时以及如何将桶从链表转换为红黑树?

标签 java java-8 hashmap

<分区>

我研究了 Java 8 的特性,发现当桶上的条目集数量增加时, HashMap 使用红黑树而不是链表。

但是,这不要求键是 Comparable 或键的某些顺序存在吗?这是如何工作的?这种转换实际上何时发生以及如何发生?

最佳答案

当单个桶中至少 8 个条目(TREEIFY_THRESHOLD)并且桶总数超过 64 个(MIN_TREEIFY_CAPACITY ) 然后该单个桶将转换为完美平衡的红黑树节点

当您删除条目 (UNTREEIFY_THRESHOLD == 6) 时,您还应该注意(如果需要)收缩。

你认为键应该是 Comparable 是正确的——但这并不总是必需的,如果它们是这样就好了(以防它们具有相同的 hashCode),但是如果不是,则使用:

 static int tieBreakOrder(Object a, Object b) {
        int d;
        if (a == null || b == null ||
            (d = a.getClass().getName().
             compareTo(b.getClass().getName())) == 0)
            d = (System.identityHashCode(a) <= System.identityHashCode(b) ?
                 -1 : 1);
        return d;
 }

因此作为 String 的 className 用于比较,如果也失败,则使用 System.identityHashCode(Marsaglia XOR-Shift 算法)来决定 < em>左 和

当发生这种情况时回答您的问题 - 当调用 resize 时。当您必须调整 HashMap 的大小时 - 会发生一些事情;就像桶的数量增加两倍(考虑条目将移动或不移动的位置多了一位)或某个桶被转换为树。这个过程(如果你真的很在意的话)非常慢,有人说 Java HashMap 是“sloooooooow,然后是快快快快;然后它是 sloooooo,然后它快快快快”(我仍然认为这是 mock ,但有是 PauselessHashMap 实现)。

这带来了两个有趣的观点。首先是选择正确的 Map 大小(即使粗略估计也可以),即:

 new HashMap<>(256); // choosing the size

这将避免一些调整大小。

第二个是为什么转换为 Tree 很重要(想想数据库索引以及为什么它们是 BTREE...)。在具有 INTEGER.MAX_VALUE 条目(理论上)的完美树中找到条目需要多少步。最多只有 32 个。

关于java - HashMap 何时以及如何将桶从链表转换为红黑树?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47921663/

相关文章:

java - Jackson XmlMapper 将XML转换为POJO,节点文本的键是 ""

java - JAX-RS 和 CDI/@Provider 和 beans.xml

android - java.lang.NoSuchMethodError in external java dependency inside the java dependency from Kotlin on Android 5

Java - 自定义 HashMap /表的一些要点

java - spring-rabbitmq 自动重试连接到代理

java - 如何添加一个 double 值和一个 double 列表元素?

lambda - Java 8 类型推断错误,将 lambda 表达式分配给 Object 类型的变量

java - 如何为方法返回的流启用 "type information"?

java - 重写 HashMap 实现的 equals() 和 hashCode() 方法

java - 将 hashMap 存储在数组中