目录
一、ArrayList使用
在介绍底层实现之前先来介绍一下ArrayList的基本使用方法,大家可以自己运行一下,看一下运行结果。
List<String> nameList = new ArrayList<>();
// 添加三个元素
nameList.add("张三");
nameList.add("李四");
nameList.add("王五");
// 取出第一个元素
String firstName = nameList.get(0);
System.out.println("第一个元素:" + firstName);
// 删除第一个元素
String removeName = nameList.remove(0);
System.out.println("删除元素:" + removeName);
System.out.println("====for循环遍历====");
// 遍历nameList,第一种方法:for循环
for (String name : nameList) {
System.out.println(name);
}
System.out.println("====foreach遍历====");
// 遍历nameList, 第二种方法:foreach
nameList.forEach(System.out::println);
System.out.println("====迭代器遍历====");
// 遍历nameList, 第三种方法:迭代器
Iterator<String> nameIterator = nameList.iterator();
while (nameIterator.hasNext()) {
System.out.println(nameIterator.next());
}
二、ArrayList继承关系
ArrayList类的继承关系如下,一般认为一个类实现类某个接口或继承了某个类,这个类具有某个类或接口的能力。
自底向上分析,ArrayList实现了RandomAccess接口说明ArrayList具有随机访问元素的能力,实现了Cloneable接口,说明ArrayList可以进行深拷贝,ArrayList还实现了Serializable接口,说明它是可以被序列化的,并且ArrayList还实现了List接口。
除此之外,ArrayList还继承了AbstractCollection抽象类,可以复用一些父类已经实现的方法,这里应用了一种经典设计模式—模板方法模式。
AbstractCollection和List又分别实现和继承了Collection接口,Collection接口又继承了Iterable,也就是说所有Collection接口的实现类,都具有迭代元素的能力。
三、ArrayList的构造方法
ArrayList正如它的名字,它存储数据采用了数组这种数据结构,所有的数据保存在ArrayList的成员变量elementData数组中,并且标记了transient,说明这个成员变量是不参与序列化的。
transient Object[] elementData;
另一个成员变量size表示了ArrayList元素的个数。
private int size;
那么ArrayList是如何初始化这个数组的呢?先从ArrayList的构造函数着手分析,ArrayList一共有三个构造函数,
最常用的就是无参构造函数,调用这个构造方法会创建一个空的数组对象。
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
DEFAULTCAPACITY_EMPTY_ELEMENTDATA是一个静态的空数组常量。
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
第二个构造方法,支持指定初始化容量,如果传入的初始容量大于0,则会按照传入的容量进行数组的初始化,如果初始化容量为0,则初始化一个空数组对象,如果初始化容量小于0,直接抛出异常。
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementDat