Java8 Hashmap 在返回常量哈希码的情况下重新哈希

标签 java java-8 hashmap

按照下面的代码,hashmap 的初始默认容量是 16,LF 是 0.75,所以当我输入第 13 个元素时,应该会发生重新散列,因为我提供了一个常量 hashcode,它在内部维护一个链表来维护插入顺序。所以,直到第 10 个元素它按预期工作但是当我输入第 11 个元素时,它会打乱顺序。 谁能帮助我理解为什么它只在第 11 个元素插入时发生。

class A{
    int a;

    A(int a){
        this.a = a;
    }
    @Override
    public int hashCode() {
        return 7;
    }
    @Override
    public String toString() {
        return "" + a + "";
    }
}
class Base {
    public static void main(String[] args) {
        Map<Object, Integer> m = new HashMap<Object, Integer>();
        m.put(new A(1), 1);
        m.put(new A(2), 1);
        m.put(new A(3), 1);
        m.put(new A(4), 1);
        m.put(new A(5), 1);
        m.put(new A(6), 1);
        m.put(new A(7), 1);
        m.put(new A(8), 1);
        m.put(new A(9), 1);
        m.put(new A(10), 1);
        //m.put(new A(11), 1);
        System.out.println(m);
    }
}

直到第 10 个元素我得到的输出:

{1=1, 2=1, 3=1, 4=1, 5=1, 6=1, 7=1, 8=1, 9=1, 10=1}

输入第 11 个元素后得到的输出:

{4=1, 1=1, 2=1, 3=1, 5=1, 6=1, 7=1, 8=1, 9=1, 10=1, 11=1}

它应该维护插入顺序,或者如果它在内部使用 RB 树,那么在这种情况下它在这里使用哪种遍历?

最佳答案

It should maintain insertion order or if it is using RB tree internally so which traversal it is using here in this case?

没有“应该”; HashMap 不保证任何顺序。当前实现中实际发生的情况由两个常量决定,TREEIFY_THRESHOLD = 8MIN_TREEIFY_CAPACITY = 64

当一个桶中的项目数超过前者时,桶将转换为节点树,除非 map 的总容量小于后者常量,在这种情况下,容量将增加一倍。

因此,当您插入第 9 个对象时,容量将从 16 增加到 32,插入第 10 个会使容量从 32 增加到 64,然后,插入第 11 个元素将导致桶转换为树。

这种转换总会发生,无论是否有实际好处。由于对象具有相同的哈希码并且未实现 Comparable,因此最终将使用它们的标识哈希码来确定顺序。这可能会导致顺序发生变化(在我的环境中,不会)。

关于Java8 Hashmap 在返回常量哈希码的情况下重新哈希,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54708134/

相关文章:

java - 什么是 JPA 实现?

java-8 - 在REST安全中,如何设置超时?

java - 解析 HashMap 中的字符串数组

java - 从 HashMap 中删除特定条目的简短方法

java - 如何从 map 中删除/删除 Entry<K,V> 列表?

java.util.SimpleTimezone 什么是 startMode 和 endMode?

java - Python 3.7 连接到 MAC 上的 HSQLDB

java - ClassNotFoundException:在全新项目中未找到类 "package.MainActivity"

mysql - grails 3.0.2 mysql 连接

Java 8 Stream 和数组操作