Java基础数据结构之ArrayList源码分析

一.几个常量

这是默认容量

这两个是共享的空对象

这是真正存储元素的地方,现在还没有分配内存

二.构造方法

Java基础数据结构之ArrayList源码分析_第1张图片

这是一个无参构造方法,此时让存储元素的数组指向了那个默认容量数组,此时该数组是一个空数组,长度为0.

Java基础数据结构之ArrayList源码分析_第2张图片

这是给定初始容量的构造方法,第一个if里面,让elementdata指向了一个新数组,而没有共享那俩个空数组,但如果给定的初始容量为0,就会共享那个空数组

Java基础数据结构之ArrayList源码分析_第3张图片

这个构造方法的参数是一个实现了Collection接口的类,其中的数据必须是E或E的子类。例如:

Java基础数据结构之ArrayList源码分析_第4张图片

我们再看源码 elementData = c.toArray(); 这是Collection接口中的一个抽象方法:

注意,其返回值是Object[]

构造方法中的第一个if是为了将elementData变成Object类,因为ArrayList是基于Object进行操作的

注意getClass得到的是运行时类型,比如

Java基础数据结构之ArrayList源码分析_第5张图片

p的编译时类型是Person类,p的运行时类型是Student类,getClass得到的是Student类

三.ArrayList扩容机制之add方法

1.在末尾添加元素

Java基础数据结构之ArrayList源码分析_第6张图片

调用第一个方法是传入了所需最小容量,即当前size+1

Java基础数据结构之ArrayList源码分析_第7张图片

Java基础数据结构之ArrayList源码分析_第8张图片

Java基础数据结构之ArrayList源码分析_第9张图片

如果所需容量小于当前数组的长度,就要grow即扩容

Java基础数据结构之ArrayList源码分析_第10张图片

旧容量是数组长度,新容量是旧容量的1.5倍!!如果新容量小于所需容量,就让新容量等于所需容量,然后扩容,用到copyOf方法

总结:

对于调用了无参构造方法的list,它的elementData指向了那个共享的空数组,长度为0,当第一次添加元素时,会进入如下方法:

Java基础数据结构之ArrayList源码分析_第11张图片

其中恰好可以进入if语句,所以会返回DEFAULT_CAPACITY即10,然后如下函数接收:

Java基础数据结构之ArrayList源码分析_第12张图片

然后1.5倍扩容

在第二次添加时,elementData不再指向DEFAULTCAPACITY_EMPTY_ELEMENTDATA,所以calculateCapacity方法返回的是minCapacity即2,所以就不会进入grow方法

2.在指定位置添加元素

Java基础数据结构之ArrayList源码分析_第13张图片

首先是检查下标的合法性,其次就是确定容量,然后就是元素后移,最后就是放置元素

四.其他方法

1.trimToSize()方法

Java基础数据结构之ArrayList源码分析_第14张图片

目的是缩小数组大小,比如数组长度是10,但只有3个元素,就将数组大小缩小为3

2.indexOf方法

Java基础数据结构之ArrayList源码分析_第15张图片

返回元素第一次出现时对应的下标

3.lastIndexOf

返回最后一次出现时对应的下标

4.

Java基础数据结构之ArrayList源码分析_第16张图片

super.clone()是一个浅拷贝,只是将链表的表面克隆过来了,链表内部的elementData没有克隆一份,而是与之前的elementData共享这一个空间,所以还要对elementData单独进行克隆。

5.toArray方法

注意,其返回值是Object类型,接收时是否可以应Integer类型接收并进行向下转型?

Java基础数据结构之ArrayList源码分析_第17张图片

报错了,这是因为在java中,父类引用可以指向子类实例,但反过来就不可以。toArray方法返回的是一个父类的实例对象,就不能用子类引用去接收。所以可以用到下面的toArray方法

Java基础数据结构之ArrayList源码分析_第18张图片

a是一个将要存储列表元素的数组,如果a的长度小于列表中的元素个数,就会重新创建一个数组,该数组长度等于列表中元素个数,类型和a的类型一致;

如果a的大小足够大,就会将elementData中的元素拷贝到a中。如果拷贝后还有剩余空间,则会将a中紧接在集合结束后的元素设置为null

看效果:

Java基础数据结构之ArrayList源码分析_第19张图片

Java基础数据结构之ArrayList源码分析_第20张图片

6.clear方法

Java基础数据结构之ArrayList源码分析_第21张图片

将元素置为null

7.retainAll方法

Java基础数据结构之ArrayList源码分析_第22张图片

Java基础数据结构之ArrayList源码分析_第23张图片

A.retainAll(B)表示将存在于A中但不存在于B中的元素移除,并更新size

8.subList方法

Java基础数据结构之ArrayList源码分析_第24张图片

返回一个子顺序表,注意区间是左闭右开

五.遍历ArrayList

Java基础数据结构之ArrayList源码分析_第25张图片

这俩个方法返回了一个Itr对象,Itr是ArrayList里面自定义的一个内部类,该类实现了Iterator接口,如下:

Java基础数据结构之ArrayList源码分析_第26张图片

注意,Iterator是一个接口,ListIterator接口继承了该接口,如下:

Java基础数据结构之ArrayList源码分析_第27张图片

所以可以如下使用:

Java基础数据结构之ArrayList源码分析_第28张图片

Java基础数据结构之ArrayList源码分析_第29张图片

你可能感兴趣的:(数据结构)