Java-ArrayList的使用与源码简析

ArrayList作为最常用的数据结构,它的源码应该是每个java coder都要掌握的。

1. 继承关系图谱

2. 特征

有序,元素可重复。

3. 源码简析(基于jdk1.8)

在Java中,数组是堆内存上一块连续的内存区间,通过索引能以O(1)的速度来访问数组元素。但数组有个不足之处,就是数组创建时,它所占的内存空间就是确定的,即它能持有的元素数量就是确定的。有时我们不能确定需要持有的元素数量,这时一般就会用到ArrayList。

ArrayList的底层就是通过数组实现的,查看源码:

Object类型的数组用于持有元素,size记录持有的元素数量。elementData用transient修饰表示不可直接序列化,这是因为elementData中可能存在未用到的数组空间,无需将整个elementData序列化,ArrayList提供了writeObject方法来进行序列化。

ArrayList实现的关键就在于它对elementData的复制扩充,直接看add方法:

在添加元素前,ArrayList会进行容量计算,若需要的容量超过了数组的容量,则对数组进行扩容。扩容的方法是实例化一个新的数组对象,其容量是现有数组容量的1.5倍,然后将elementData持有的元素复制到新的数组对象,最后将elementData的引用指向新的数组对象,原有的数组对象因为没有了引用,一段时间后将被回收。

ArrayList默认的插入是插在数组的末尾,在不需要扩容时是一个时间复杂度O(1)的操作,需要扩容时复杂度为O(n),所以如果预先能判断数据量的大小,可以指定初始化数组的大小,避免过多的扩容操作。ArrayList还支持在指定索引处插入。源码如下:

在指定索引处插入时,需要将指定索引及其之后的元素向后推一个位置,所以是一个复杂度O(n)的操作。此外,删除元素时,需要将所删元素之后位置的元素都向前推一个位置,复杂度也是O(n)。所以ArrayList不适合需要频繁在指定位置插入元素及删除的应用场景

ArrayList获取指定索引处元素的复杂度为O(1),当ArrayList用于查找元素时,需要遍历数组,因此是一个复杂度O(n)的操作。

4. 总结

ArrayList底层采用数组实现,是一个用于持有元素的有序、元素可重复的容器。适用于需要查找指定索引处元素的场景。当需要频繁插入、删除元素,或者查找指定元素时,其复杂度为O(n)。

你可能感兴趣的:(Java-ArrayList的使用与源码简析)