可以存储在 HashMap 中的键(对象)数量的理论限制?

Posted

技术标签:

【中文标题】可以存储在 HashMap 中的键(对象)数量的理论限制?【英文标题】:Theoretical limit for number of keys (objects) that can be stored in a HashMap? 【发布时间】:2011-05-06 15:24:57 【问题描述】:

对于可以存储在 HashMap 中的键条目的数量是否有理论上的限制,或者最大值是否完全取决于可用的堆内存?

另外,哪种数据结构最适合存储大量对象(比如几十万个对象)?

【问题讨论】:

您是要询问唯一键的数量还是条目数?我可以发誓 HashMap 是用桶构建的,所以虽然最多有 Integer.MAX_VALUE 个桶,但每个桶都可以有一个包含许多条目的列表。 有趣的问题,得到我的 +1 不同的人对大有不同的想法。你能更具体一点,你的意思是100、1000、数百万、数百万、数万亿吗? 是的,我已经指定了大小(几十万或几百万) 最喜欢的问题有我的 +1 【参考方案1】:

HashMap 将值保存在一个数组中,该数组最多可以保存Integer.MAX_VALUE。但这不包括碰撞。每个Entry 都有一个next 字段,这也是一个条目。这就是解决冲突(具有相同哈希码的两个或多个对象)的方式。所以我不会说有任何限制(除了可用内存)

请注意,如果您超过 Integer.MAX_VALUE,您将在某些方法(如 size())中得到意外行为,但 get()put() 仍然有效。它们会起作用,因为任何对象的hashCode() 都将返回int,因此根据定义,每个对象都将适合地图。然后每个对象都会与现有对象发生碰撞。

【讨论】:

HashMap#size() 的文档实际上将键值映射的数量限制为一个 int 可以表示的数字。如果 HashMap 允许更多映射,则 size() 方法的文档将继承自 Map#size(),它定义了在大小 > Integer.MAX_VALUE 时返回 Integer.MAX_VALUE 的方法。 hashCode() 返回int。因此,桌子满了之后,只会有碰撞。【参考方案2】:

对于可以存储在 HashMap 中的键条目的数量是否有理论上的限制,还是完全取决于可用的堆内存?

看看the documentation of that class,我会说理论极限是Integer.MAX_VALUE (231-1 = 2147483647) 个元素。

这是因为要正确实现此类,size() 方法必须返回一个 int,表示键/值对的数量。

来自HashMap.size()的文档

返回:此映射中键值映射的数量

注意:这个问题与How many data a list can hold at the maximum非常相似。


哪种数据结构最适合存储大量对象(比如几十万个对象)?

我会说这取决于您需要存储什么以及您需要什么类型的访问权限。所有内置集合可能都针对大批量进行了优化。

【讨论】:

我刚刚注意到 size():int 方法:) 其实size()并不是真正的问题:如果地图包含多个Integer.MAX_VALUE元素,则返回Integer.MAX_VALUE - download.oracle.com/javase/6/docs/api/java/util/Map.html#size()只有客户端代码没有识别size()的真正含义应该是个问题。 @gustafc,啊,有趣的一点。但是,HashMap.size() 的文档完善了该规范:download.oracle.com/javase/6/docs/api/java/util/… 不过,这是否可能是规范中的“错误”值得怀疑 :-) @aioobe - 好吧,看看HashMap 的Sunoracle 实现,size 字段可能会溢出似乎并没有真正令人惊讶。规范合规性? :) 所以也许我应该说“size() 不应该真的不是问题”... @jarnbjo,我不完全相信这不会被修复 - 我们也可以争辩说可能有代码依赖于 HashMap 正确实现 Map。当我或 aioobe 的错误报告得到回复时,我们会看看谁是对的。【参考方案3】:

我同意@Bozho 的观点,并补充说您应该仔细阅读HashMap 上的Javadoc。请注意它如何讨论初始容量和负载因子以及它们将如何影响 HashMap 的性能。

HashMap 非常适合保存大量数据(只要您没有用完键或内存),但性能可能是个问题。

如果您发现无法在单个 Java/JVM 程序中操作所需的数据集,则可能需要查看分布式缓存/数据网格。

【讨论】:

【参考方案4】:

理论上没有限制,但是存储不同入口链的桶有一个限制(存储在不同的hashkey下)。一旦达到这个限制,每次新添加都会导致哈希冲突——但这不是问题,除了性能......

【讨论】:

以上是关于可以存储在 HashMap 中的键(对象)数量的理论限制?的主要内容,如果未能解决你的问题,请参考以下文章

将数据存储为具有空/空值的 HashMap 中的键是一个好主意吗?

Kotlin HashMap包含使用数组的键

android中的键值对

HashMap源码解析

hashmap的嵌套,存储一个自定义类

第4章 字典