源码分析:
对于ArrayList应该是开发当中每天都会与之打交道的,都知道它底层是由数组来实现的,但对于它底层的具体实现细节说实话却道不出一二来,所以打开它的源代码一探究竟,先来看一下应用代码:
先查看一下它的类继承体系:
比较复杂,接着根据咱们调用的是它的默认构造方法来初始化ArrayList的,所以看一下默认构造:
好,接着咱们来往ArrayList集合中添加元素,其应用代码如下:
所以从源码角度来看一下这个add的实现细节:
看方法中的第一句:
从英文的字面意思应该是确保集合的容量相关的东东,其中有一个size变量,先了解一下它:
因为目前还木有元素当然size=0,所以ensureCapacity的参数为1,接着分析一下ensureCapacity的具体实现:
接着判断minCapacity > oldCapacity是否满足,目前1 > 10条件不满足,也就不会执行条件里面的语句,然后方法返回到主流程:
好!!如果add()了第10个元素,ensureCapacity(11),此时就会大于默认的10个长度的数组了,所以就会执行它里面的判断条件了,如下:
那Arrays.copyOf()的具体作用是啥呢?它的总容量的个数会变成newCapacity个数了,但是前面的元素是之前元素elementData的内容,等于就是扩容了,原来只能容下10个元素,而这次扩容之后就变为16个元素了,前10个元素是之前的内容,而后面6个元素是空的元素。
好~明白了add()方法之后,接下来在应用时会从集合中拿数据,所以会调用它:
所以定位到该方法的源码:
首先会做范围检查,这个比较好理解,如下:
好,再回到主流程:
嗯~~比较简单,接着再看一个新方法:
明显比get()方法要复杂多了,下面一一分析:
在返回之前还会做如下操作,这也是删除代码的核心逻辑:
其实上面代码就是移位的操作,下面用图来表示一下:
可见对于ArrayList的删除操作的代价是相当的高的。
总结:
- ArrayList底层采用数组实现,当使用不带参数的构造方法生成ArrayList对象时,实际上会在底层生成一个长度为10的Object类型的数组。
- 如果增加的元素个数超过了10个,那么ArrayList底层会新生成一个数组,长度为原数组的1.5倍+1,然后将原数组的内容复制到新数组当中,并且后续增加的内容都会放到新数组当中,当新数组无法容纳增加的元素时,重复该过程。
- 对于ArrayList元素的删除操作,需要将被删除元素的后续元素向前移动,代价比较高。
- 集合当中只能放置对象的引用,无法放置原生数据类型,我们需要使用原生数据类型的包装类才能加入到集合当中。
- 集合当中放置的都是Object类型,因此取出来的也是Object类型,那么必须要使用强制类型转换将其转换成真正的类型(放置进去的类型)。