ArrayList 和 LinkedList 空间大小我们可以从两个方面进行对比:
- 每个单元所占空间大小
- 整体所占空间大小
1. 每个单元所占空间大小
众所周知,ArrayList 的数据底层是数组,而 LinkedList 的数据底层是双向链表。
数组每个单元只有一个元素值,无其他,而双向链表每个单元除了元素值还有两个结点存储上一和下一单元。所以 ArrayList 比 LinkedList 省空间。
2. 整体所占空间大小
ArrayList:从源码可知,arrayList 初始时的数组容量为 0,当添加数据时,它会自动生成一个 10 容量的数组。并且每当数据要溢出时会自动扩容 1.5 倍。
LinkedList:从源码可知,LinkedList 初始时生成一个头结点,当添加数据时,它会生成结点连接到头结点上。
故初始时,arrayList 比 LinkedList 省空间。
但从表面上看,每当数组添加第一个元素时,都会增加 10 个空间,且每当数据溢出时,都会扩容 1.5 倍空间,这都是满满的空间浪费呀!!!
事实真的这样吗?
从源码中看 ArrayList:
- 数组的定义:
transient Object[] elementData;
transient 是一个关键字,它的作用为:在不需要序列化的属性前添加 transient,每当序列化对象的时候,这个属性就不会被序列化(序列化即是能够解析成字节码)。即不管数组有多大,都不会解析成字节码,不开括空间。
ArrayList 这个类是实现了 java.io.Serializable 接口的,即这个类是能够被序列化为字节码文件,但里面的数组却没有被解析为字节码。
- 继续往下看:数组没有序列化,那他怎么存储元素?
ArrayList 里重写了 writeObject 方法:
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject();
// Write out size as capacity for behavioural compatibility with clone()
s.writeInt(size);
// Write out all elements in the proper order.
for (int i=0; i<size; i++) {
s.writeObject(elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
其中,defaultWriteObject() 方法是序列化 ArrayList 类中无 transient 元素,即没有序列化 elementData 数组,接着通过 for 循环遍历 elementData 数组,把里面有值的元素序列化。
这样一来,在内存中的空间只开辟了有值的数组元素,并不会造成空间的浪费。
所以:
ArrayList 比 LinkedList 省空间!!!
ArrayList 比 LinkedList 省空间!!!
ArrayList 比 LinkedList 省空间!!!
感兴趣的朋友可以关注下公众号《慢慢编程》,慢慢在这里磕头了!