HashSet,Vector,LinkedList的最大大小

div*_*ivz 28 java collections

什么是最大尺寸HashSet,Vector,LinkedList?我知道ArrayList可以存储超过3277000个数字.

但是列表的大小取决于内存(堆)大小.如果达到最大值,JDK会抛出一个OutOfMemoryError.

但我不知道元素数量的限制HashSet,VectorLinkedList.

Joa*_*uer 55

这些结构没有指定的最大尺寸.

实际的实际大小限制可能在某个区域Integer.MAX_VALUE(即2147483647,大约20亿个元素),因为这是Java中数组的最大大小.

  • A HashSetHashMap内部使用,因此它具有相同的最大尺寸
    • A HashMap使用的数组总是具有2的幂,因此它最多可以是2 30 = 1073741824个元素(因为2的下一个幂大于Integer.MAX_VALUE).
    • 通常,元素的数量最多是桶的数量乘以负载因子(默认为0.75).但是,当HashMap停止调整大小时,它仍然允许您添加元素,利用每个存储桶通过链接列表进行管理的事实.因此,HashMap/中元素的唯一限制HashSet是内存.
  • A Vector在内部使用一个数组,其最大大小完全正确Integer.MAX_VALUE,因此它不能支持多个元素
  • A LinkedList 使用数组作为底层存储,因此不会限制大小.它使用经典的双向链表结构,没有固有限制,因此其大小受可用内存的限制.请注意,LinkedList如果它比我的大错误地将报告的大小Integer.MAX_VALUE,因为它使用一个int字段来存储的大小和返回类型size()int为好.

请注意,虽然CollectionAPI 确实定义了Collection多个Integer.MAX_VALUE元素应该如何表现.更重要的是它指出此size()文档:

如果此集合包含多个Integer.MAX_VALUE元素,则返回Integer.MAX_VALUE.

需要注意的是,虽然HashMap,HashSet并且LinkedList 似乎支持超过Integer.MAX_VALUE元素,没有那些实施size()这种方式方法(即它们只是让内部size字段溢出).

这让我相信在这种情况下其他操作没有明确定义.

所以我说这是安全使用的通用集合与多达 Integer.MAX_VLAUE元素.如果您知道您需要存储更多内容,那么您应该切换到实际支持此功能的专用集合实现.


Jon*_*eet 8

在所有情况下,您可能会受到JVM堆大小的限制,而不是其他任何东西.最终你总是会遇到阵列,所以我非常怀疑他们中的任何一个都会管理超过2个31 - 1个元素,但是在此之前你很可能会用完堆.


Pet*_*rey 5

这在很大程度上取决于实现细节。

HashSet 使用一个数组作为底层存储,默认情况下它会在集合达到 75% 时尝试增长。这意味着如果您尝试添加超过 750,000,000 个条目,它将失败。(它不能将数组从 2^30 增加到 2^31 个条目)

增加负载因子会增加集合的最大大小。例如,10 的负载因子允许 100 亿个元素。(值得注意的是,HashSet 在超过 1 亿个元素时效率相对较低,因为 32 位哈希码的分布开始看起来不那么随机,并且冲突次数增加)

Vector 将其容量加倍并从 10 开始。这意味着它无法增长到大约 13.4 亿以上。将初始大小更改为 2^n-1 可为您提供更多的头部空间。

顺便说一句:如果可以,请使用 ArrayList 而不是 Vector。

LinkedList 没有固有限制,可以增长到 21 亿以上。此时 size() 可以返回 Integer.MAX_VALUE,但是某些函数(例如 toArray)将失败,因为它无法将所有对象放入数组中,而 in 将为您提供第一个 Integer.MAX_VALUE 而不是抛出异常。

正如@Joachim Sauer 所指出的,当前的 OpenJDK 可能会为大于 Integer.MAX_VALUE 的大小返回错误的结果。例如,它可能是一个负数。