我需要存储大量信息,例如java list中的'names'。项目数量可以改变(或者简而言之,我不能预定义大小)。我认为,从内存分配的角度来看,LinkedList比ArrayList更好,对于ArrayList,一旦达到最大大小,内存分配自动加倍,因此总是有可能分配比内存更多的内存。需要什么。
我从其他帖子中了解到,存储在LinkedList中的单个元素占用的空间比ArrayList多,因为LinkedList也需要存储节点信息,但我仍然猜测我已定义的场景LinkedList可能是更好的选择。此外,我不想进入性能方面(获取,删除等),因为已经讨论过它。
答案 0 :(得分:51)
LinkedList
可能会分配更少的条目,但这些条目在天文数字上比ArrayList
更昂贵 - 足以使最差情况ArrayList
更便宜关注记忆。
(仅供参考,我认为你错了; ArrayList
当它已满时增长1.5倍,而不是2倍。)
参见例如https://github.com/DimitrisAndreou/memory-measurer/blob/master/ElementCostInDataStructures.txt:LinkedList
每个元素消耗24个字节,而ArrayList
每个元素最多消耗4个字节,最坏的情况是每个元素消耗6个字节。 (结果可能因32位与64位JVM和压缩对象指针选项而异,但在这些比较LinkedList
中至少需要36个字节/元素,而ArrayList
最多只需8个最糟糕的12。)
更新:
我从其他帖子中了解到,存储在LinkedList中的单个元素占用的空间比ArrayList多,因为LinkedList也需要存储节点信息,但我仍然猜测我已定义的场景LinkedList可能是更好的选择。此外,我不想进入性能方面(获取,删除等),因为已经讨论过它。
要明确的是,即使在最坏情况中,ArrayList
比具有相同元素的LinkedList
小4倍。使LinkedList
获胜的唯一可行方法是通过调用ensureCapacity
故意夸大价值来故意修正比较,或者在添加ArrayList
之后删除大量值
简而言之,基本上不可能让LinkedList
赢得内存比较,如果你关心空间,那么在trimToSize()
上调用ArrayList
会立即生成ArrayList
再次大获全胜。认真。 ArrayList
获胜。
答案 1 :(得分:5)
...但我仍在猜测我已定义的场景LinkedList可能是更好的选择
你的猜测不正确。
一旦超过了数组列表的初始容量,支持的大小将在1到2个引用之间乘以条目数。这是由于用于增长后备阵列的策略。
对于链表,每个节点至少占条目数的3倍,因为每个节点都有next
和prev
引用以及条目引用。 (事实上,它超过3次,因为节点的对象头和填充使用了空间。根据JVM和指针大小,它可以多达6次。)
链接列表使用的空间少于数组列表的唯一情况是,如果您严重高估了数组列表的初始容量。 (对于非常小的清单......)
当你考虑它时,唯一真正的优势链表就是数组列表就是在插入和删除元素时。即便如此,这取决于你是如何做到的。
答案 2 :(得分:2)
ArrayList.trimToSize()可能会让您满意。
将此ArrayList实例的容量调整为列表的当前容量 尺寸。应用程序可以使用此操作来最小化存储 一个ArrayList实例。
顺便说一句,在ArrayList Java6中,它不是双倍容量,它是最大大小的1.5倍。
答案 3 :(得分:2)
ArrayList每个对象使用一个引用(或者当它需要的大小加倍时使用两个引用)这通常是4个字节。
LinkedList仅使用其需要的节点,但每个节点可以是24个字节。
所以即使在最糟糕的情况下,ArrayList也会比LinkedList小3倍。
用于获取ARrayList支持随机访问O(1)但LinkedList是O(n)。为了从末尾删除,两者都是O(1),从中间的某个地方删除ArrayList是O(n)
除非您有数百万条目,否则收集的大小不太重要。首先重要的是条目的大小,无论使用何种集合,都是相同的。
答案 4 :(得分:2)
信封背面最坏情况:
数组中500,000个名称大小为1,000,000 = 500,000使用,500,000个空指针位于已分配数组的未使用部分。
链表中的500,000个条目=每个条目3个指针(节点对象保持当前,上一个和下一个)=内存中的1,5000,000个指针。 (然后你必须添加节点本身的大小)