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