java - HashMap绝对容量

标签 java hashmap

我一直在对代码中的一个 HashMap 对象进行一些性能检查,发现它会减慢在大约 2000-2400 个对象内添加对象的速度。事实上,当它达到大约 2400 个对象时,它仍然处于阻塞状态并且不允许更多条目。这种对象是否有一个限制,当它们被保存在内存中时,在它们被清空或回收之前不允许更多的条目?

非常感谢。

最佳答案

我能想到的唯一可以解释这个问题的事情是,如果你的对象非常大并且你几乎用完了堆。发生这种情况时,JVM 可能会停止越来越长的时间来尝试清理。在 Java 6 中,它尝试在情况变得非常糟糕之前检测到这一点并抛出 OutOfMemoryError(在它完全耗尽但未能清理太多之前),Java 5.0 不会这样做。

这可以解释为什么当你丢弃一些物体时事情会再次加速。

<小时/>

HashMap 的标准实现限制为大约 7.5 亿个条目(取决于您如何使用它,例如您的平均负载)它可以拥有的最大容量为 2^30(十亿),负载因子为 0.75f( ~750m 条目)它将尝试将底层数组增大到该大小的两倍,但它无法做到这一点。 (由于最大大小为 Integer.MAX_VALUE)

您可以使用 LinkedHashMap 作为缓存,根据您必须提供的规则驱逐“eldset”条目。

但是,除非 HashMap 是同步的,否则它不会阻塞。如果失败,它将抛出异常。

让 Map 以这种方式阻塞的唯一一致方法是产生死锁。

发生这种情况的另一种情况是,如果您以不安全的方式在两个线程中使用相同的映射。在这种情况下,行为是未定义的,但是我已经看到它在 JVM 中引起问题(非常罕见),甚至“挂起”所涉及的线程。即使是这种情况,我预计它会随着 HashMap 的增长而增长,默认负载因子为 3072(即 4096*0.75),而不是您看到的值。

<小时/>

即使 hashCode 实现不好也无法解释这个问题。

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

public static void main(String... args) {
    Map<BadHash, Boolean> map = new HashMap<BadHash, Boolean>();
    for (int i = 0; i <= 100000; i++) {
        if (i % 10000 == 0) System.out.println(i + ": " + new Date());
        map.put(new BadHash(), true);
    }
}

在 14 秒内打印以下内容。

0: Mon Sep 26 12:23:39 BST 2011
10000: Mon Sep 26 12:23:39 BST 2011
20000: Mon Sep 26 12:23:39 BST 2011
30000: Mon Sep 26 12:23:40 BST 2011
40000: Mon Sep 26 12:23:41 BST 2011
50000: Mon Sep 26 12:23:42 BST 2011
60000: Mon Sep 26 12:23:44 BST 2011
70000: Mon Sep 26 12:23:46 BST 2011
80000: Mon Sep 26 12:23:48 BST 2011
90000: Mon Sep 26 12:23:51 BST 2011
100000: Mon Sep 26 12:23:53 BST 2011

关于java - HashMap绝对容量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7554106/

相关文章:

java - Protocol Buffer : From Java to Objective-C using byte[]

java - 私有(private)成员不被继承。那么 getter 和 setter 如何访问子类中的私有(private)字段呢?

java - 在循环中保存集合

java - 为什么在 LinkedHashMap 中通过桶迭代比 HashMap 更快?

java - Autowiring 来自 Spring @Configuration 类的字符串?

java - Equinox:通过包正确导出和导入类,但仍然出现 ClassNotFoundException

java - 二维数组作为类变量

java - 在 Java 8 中构建 Map 以进行集成测试的重构方法 - 函数式编程的机会?

java - 在 REST Assured 中,如何使用参数映射?

java - 使用 apache POI 将 hashmap 的每个元素(键值对)写入同一工作簿中的不同 Excel 工作表