ArrayList 比 LinkedList 更省空间?

899 阅读3分钟

ArrayList 和 LinkedList 空间大小我们可以从两个方面进行对比:

  1. 每个单元所占空间大小
  2. 整体所占空间大小

1. 每个单元所占空间大小

众所周知,ArrayList 的数据底层是数组,而 LinkedList 的数据底层是双向链表。
数组每个单元只有一个元素值,无其他,而双向链表每个单元除了元素值还有两个结点存储上一和下一单元。所以 ArrayList 比 LinkedList 省空间。

2. 整体所占空间大小

ArrayList:从源码可知,arrayList 初始时的数组容量为 0,当添加数据时,它会自动生成一个 10 容量的数组。并且每当数据要溢出时会自动扩容 1.5 倍。
LinkedList:从源码可知,LinkedList 初始时生成一个头结点,当添加数据时,它会生成结点连接到头结点上。

故初始时,arrayList 比 LinkedList 省空间。

但从表面上看,每当数组添加第一个元素时,都会增加 10 个空间,且每当数据溢出时,都会扩容 1.5 倍空间,这都是满满的空间浪费呀!!!

事实真的这样吗?

从源码中看 ArrayList:

  1. 数组的定义:
1transient Object[] elementData;

transient 是一个关键字,它的作用为:在不需要序列化的属性前添加 transient,每当序列化对象的时候,这个属性就不会被序列化(序列化即是能够解析成字节码)。即不管数组有多大,都不会解析成字节码,不开括空间。

ArrayList 这个类是实现了 java.io.Serializable 接口的,即这个类是能够被序列化为字节码文件,但里面的数组却没有被解析为字节码。


  1. 继续往下看:数组没有序列化,那他怎么存储元素?
    ArrayList 里重写了 writeObject 方法:
 1private void writeObject(java.io.ObjectOutputStream s)
 2    throws java.io.IOException{
 3    // Write out element count, and any hidden stuff
 4    int expectedModCount = modCount;
 5    s.defaultWriteObject();
 6
 7    // Write out size as capacity for behavioural compatibility with clone()
 8    s.writeInt(size);
 9
10    // Write out all elements in the proper order.
11    for (int i=0; i<size; i++) {
12        s.writeObject(elementData[i]);
13    }
14
15    if (modCount != expectedModCount) {
16        throw new ConcurrentModificationException();
17    }
18}

其中,defaultWriteObject() 方法是序列化 ArrayList 类中无 transient 元素,即没有序列化 elementData 数组,接着通过 for 循环遍历 elementData 数组,把里面有值的元素序列化。

这样一来,在内存中的空间只开辟了有值的数组元素,并不会造成空间的浪费。

所以:

ArrayList 比 LinkedList 省空间!!!
ArrayList 比 LinkedList 省空间!!!
ArrayList 比 LinkedList 省空间!!!


感兴趣的朋友可以关注下公众号《慢慢编程》,慢慢在这里磕头了!