ArrayList源码分析
1. 扩容
Arraylist的初始容量为10,一旦达到,将会按照原容量的50%进行扩容,即elementData
数组的长度变为原来的1.5倍。
2.添加元素
我们来看一下add(int index, Object e)
这个方法:
1 | /** |
可以看到,使用了System.arraycopy
方法,源数组和目标数组都是elementData
,将index
及其之后的元素复制到index+1
的位置。
3. 序列化
我们发现源码中用于保存元素的elementData
的数组是被transient
修饰的,这意味着他将不被序列化。那ArrayList是如何序列化的呢?我们可以发现,ArrayList自己实现了两个方法:readObject
、writeObject
用于自定义序列化,避免采用Java原生的序列化。那为什么要这么做呢?在writeObject
方法中,可以看到只是将size
范围内的元素进行序列化,这是由于前面讲过的扩容机制,导致elementData
的长度大于size
,size
索引之后都不保存具体元素值(或者说只为数组初始化的值),但确已经申请了内存空间,如果全部序列化,那么将会浪费大量空间来存储这些无用的信息。我们可以通过下面一个例子来具体演示。
我们可以看到,一个长度为20000的数组只保存了5个元素,如果直接将这个数组序列化,大小是79kb,若只将5个元素序列化,序列化后的文件大小仅为1kb。
1 | import java.io.FileOutputStream; |