当我们说数组内存分配时,它意味着在堆区域中分配的连续内存块。因此,假设数组中有100k个元素,JVM将查看堆区域,其中100k个连续内存块是空闲的。
根据理论,java Collection不是这种情况。收集下的所有元素都将通过哈希码分配到堆内存中,它可能是也可能不是连续的内存块。
现在我很困惑Collection如何以这种方式工作,因为Collection底层实现仅使用数组(例如ArrayList),这意味着数组的所有属性对Collection也是有效的。
需要帮助才能明确这一点。
答案 0 :(得分:3)
如果Collection实现是ArrayList,那么与Object []相比几乎没有开销,其他实现可能占用更多的内存来保存相同数量的元素。例如。 LinkedList为每个元素都有一个节点:
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
元素的内存大约是Object []
的5倍答案 1 :(得分:1)
由于ArrayList包装数组以提供可调整大小的存储,因此它需要的内存多于数组,而数组是一个连续的内存块,它已经知道当前的元素数。
答案 2 :(得分:1)
显然,事实内存消耗取决于正在运行的虚拟机作为对象的内存布局未由JVMS指定。使用OpenJDK附带的Java object layout等实用程序,您可以分析HotSpot上的实际实例大小。以下输出对于具有压缩OOPS的64位HotSpot v8_20b16实例有效。在此设置中,ArrayList
实例消耗:
java.util.ArrayList object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 12 (object header) N/A
12 4 int AbstractList.modCount N/A
16 4 int ArrayList.size N/A
20 4 Object[] ArrayList.elementData N/A
Instance size: 24 bytes (estimated, the sample instance is not available)
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
而Object[]
消耗:
java.lang.Object[] object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 12 (object header) N/A
12 4 (loss due to the next object alignment)
Instance size: 16 bytes (estimated, the sample instance is not available)
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
由此看来,ArrayList
似乎比数组大得多。但是,我们应该查看实际实例,以便分析由集合的存储基础架构引起的开销并计算深度。让我们为Object[]
数组和每1000个new Object()
元素的列表执行此操作:
java.util.ArrayList instance footprint:
COUNT AVG SUM DESCRIPTION
1 4016 4016 [Ljava.lang.Object;
1000 16 16000 java.lang.Object
1 24 24 java.util.ArrayList
1002 20040 (total)
[Ljava.lang.Object; instance footprint:
COUNT AVG SUM DESCRIPTION
1 4016 4016 [Ljava.lang.Object;
1000 16 16000 java.lang.Object
1001 20016 (total)
这几乎相同,因为ArrayList
数组上Object[]
的开销是不变的。与LinkedList
相比,避免LinkedList$Entry
s的大小非常小:
java.util.LinkedList instance footprint:
COUNT AVG SUM DESCRIPTION
1000 16 16000 java.lang.Object
1 24 24 java.util.LinkedList
1001 24 24024 java.util.LinkedList$Entry
2002 40048 (total)
但是,不要过高估计单一分配的影响。留意您的记忆消耗,而是使用最符合您兴趣的集合类型。如果您发现问题,优化是适当的。