HashSet
,Vector
,LinkedList
的最大尺寸是多少?我知道ArrayList
可以存储超过3277000个数字。
但是列表的大小取决于内存(堆)大小。如果达到最大值,JDK将抛出OutOfMemoryError
。
但我不知道HashSet
,Vector
和LinkedList
中元素数量的限制。
答案 0 :(得分:53)
这些结构没有指定的最大尺寸。
实际的实际大小限制可能在Integer.MAX_VALUE
区域(即2147483647,大约20亿个元素),因为这是Java中数组的最大大小。
HashSet
在内部使用HashMap
,因此它具有相同的最大尺寸
HashMap
使用的数组总是具有2的幂,因此它最多可以是2 30 = 1073741824个元素(因为下一个2的幂)大于Integer.MAX_VALUE
)。HashMap
停止调整大小时,它仍然允许您添加元素,利用每个存储桶通过链接列表进行管理的事实。因此,HashMap
/ HashSet
中元素的唯一限制是内存。Vector
内部使用一个数组,其最大大小为Integer.MAX_VALUE
,因此它不能支持多个元素LinkedList
不使用数组作为底层存储,因此不会限制大小。它使用经典的双向链表结构,没有固有限制,因此其大小仅由 以可用内存为界。请注意,如果LinkedList
大于Integer.MAX_VALUE
,int
会错误地报告大小,因为它使用size()
字段来存储大小,int
的返回类型为{ {1}}也是。请注意,虽然Collection
API 确实定义了Collection
个元素超过Integer.MAX_VALUE
的行为。最重要的是它说明了the size()
documentation:
如果此集合包含多个
Integer.MAX_VALUE
元素,则返回Integer.MAX_VALUE
。
请注意,虽然HashMap
,HashSet
和LinkedList
似乎支持的不仅仅是Integer.MAX_VALUE
个元素,但 none 其中以这种方式实现size()
方法(即它们只是让内部size
字段溢出。)
这让我相信其他操作也在这种情况下没有明确定义。
所以我说使用最多 Integer.MAX_VLAUE
元素的通用集合是安全。如果您知道您需要存储更多内容,那么您应该切换到实际支持此功能的专用集合实现。
答案 1 :(得分:8)
在所有情况下,您可能会受到JVM堆大小的限制,而不是其他任何东西。最终你总是会遇到数组,所以我非常怀疑他们中的任何一个都会管理超过2个 31 - 1个元素,但是你很可能会在那之前耗尽堆反正。
答案 2 :(得分:3)
最大大小取决于JVM的内存设置,当然还有可用的系统内存。每个列表条目的特定内存消耗大小在不同平台之间也有所不同,因此最简单的方法可能是运行简单的测试。
答案 3 :(得分:3)
这在很大程度上取决于实施细节。
HashSet使用数组作为底层存储,默认情况下,当集合75%已满时,它会尝试增长。这意味着如果您尝试添加超过750,000,000个条目,它将失败。 (它不能将数组从2 ^ 30增长到2 ^ 31个条目)
增加负载系数会增加集合的最大大小。例如载荷因子为10允许100亿个元素。 (值得注意的是,HashSet相对于1亿个元素的效率相对较低,因为32位哈希码的分布开始看起来不那么随机,并且冲突的数量增加了)
Vector的容量增加一倍,从10开始。这意味着它将无法增长到大约13.4亿。将初始大小设置为2 ^ n-1会让您的头部空间略微增加。
BTW:如果可以,请使用ArrayList而不是Vector。
LinkedList没有任何限制,可以超过21亿。此时size()可以返回Integer.MAX_VALUE,但是某些函数(如toArray)将失败,因为它无法将所有对象放入数组中,而是会给出第一个Integer.MAX_VALUE而不是抛出异常。
正如@Joachim Sauer指出的那样,当前的OpenJDK可能会返回大于Integer.MAX_VALUE的错误结果。例如它可能是一个负数。
答案 4 :(得分:2)
如其他答案中所述,阵列无法达到2 ^ 31个条目。其他数据类型受此限制,或者最终可能误报其大小()。但是,在某些系统上无法达到这些理论极限:
在32位系统上,可用字节数不会超过2 ^ 32。这假设你没有操作系统占用内存。 32位指针是4个字节。任何不依赖于数组的东西必须每个条目至少包含一个指针:这意味着对于不使用数组的东西,最大条目数为2 ^ 32/4或2 ^ 30。
普通数组可以达到它的理论极限,但只有一个字节数组,一个长度为2 ^ 31-1的短数组将消耗大约2 ^ 32 + 38字节。
一些Java VM引入了一个使用压缩指针的新内存模型。通过调整指针对齐,可以用32字节指针引用稍多于2 ^ 32个字节。大约四倍多。这足以导致LinkedList size()变为负数,但不足以允许它回绕到零。
64位系统有64位指针,使所有指针的数量增加了一倍,使非数组列表更加丰富。这也意味着支持的最大容量会精确地跳到2 ^ 64个字节。这足以使2D阵列达到其理论最大值。 byte [0x7fffffff] [0x7fffffff]使用的内存大约等于40 + 40 *(2 ^ 31-1)+(2 ^ 31-1)(2 ^ 31-1)= 40 + 40 ( 2 ^ 31-1)+(2 ^ 62-2 ^ 32 + 1)