ArrayList源码分析
1. ArrayList简介
1.1 概述
- 容量可以动态增长,基于数组实现的List,底层是Object[]类型的数组;
- 线程不安全,数组元素允许为空;
- 它继承于AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口。
1.2 继承关系
继承关系如图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7hTf2nsc-1577954938338)(en-resource://database/4123:1)]
问题:
-
为什么要先继承AbstractList,而让AbstractList先实现List?而不是让ArrayList直接实现List?
这里是有一个思想,接口中全都是抽象的方法,而抽象类中可以有抽象方法,还可以有具体的实现方法,正是利用了这一点,让AbstractList是实现接口中一些通用的方法,而具体的类,如ArrayList就继承这个AbstractList类,拿到一些通用的方法,然后自己在实现一些自己特有的方法。 -
ArrayList实现了哪些接口?
List接口:
RandomAccess接口:这个是一个标记性接口,在遍历前进行判断,根据 List 的不同子类选择不同的遍历方式,提升算法性能。通过查看api文档,它的作用就是用来快速随机存取,有关效率的问题,在实现了该接口的话,那么使用普通的for循环来遍历,性能更高,例如ArrayList。而没有实现该接口的话,使用Iterator来迭代,这样性能更高,例如LinkedList。所以这个标记性只是为了让我们知道我们用什么样的方式去获取数据性能更好。
Cloneable接口:实现了该接口,就可以使用Object.Clone()方法了。
Serializable接口: 实现该序列化接口,表明该类可以被序列化,什么是序列化?简单的说,就是 能够从类变成字节流传输,然后还能从字节流变成原来的类。
2. ArrayList源码分析
2.1 类中属性
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
/**
* 版本号
/
private static final long serialVersionUID = 8683452581122892189L;
/**
* 默认初始化容量
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* 空对象数组
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* 默认空对象数组
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* 元素数组
*/
transient Object[] elementData;
/**
* 元素大小,默认为0
*/
private int size;
}
2.2 构造方法
无参构造方法:
/**
* 构造初始容量为10的空列表。
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
有参构造方法:
/**
* 构造具有指定初始容量的空列表。
*/
public ArrayList(int initialCapacity){
if(initialCapacity>0){
this.elementData=new Object[initialCapacity];
}else if(initialCapacity==0){
this.elementData=EMPTY_ELEMENTDATA;
}else{
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
如果自定义容量大于0,使用自定义的容量进行初始化,如果等于0,则当前数组为空数组,否则抛异常。
有参构造方法2:
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray(); //转换为数组
if ((size = elementData.length) != 0) {
// defend against c.toArray (incorrectly) not returning Object[]
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
}
else { 、
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
2.3 核心方法
2.3.1 add方法
public boolean add(E e) {
modCount++;
add(e, elementData, size);
return true;
}
private void add(E e, Object[] elementData, int s) {
// 判断当前大小是否等于最大容量,如果是进行扩容,否则直接添加,大小加1
if (s == elementData.length)
elementData = grow();
elementData[s] = e;
size = s + 1;
}
public void add(int index, E element) {
// 判断inde是否越界
rangeCheckForAdd(index);
modCount++;
final int s;
Object[] elementData;
if ((s = size) == (elementData = this.elementData).length)
elementData = grow();
System.arraycopy(elementData, index,elementData, index + 1,
s - index);
elementData[index] = element;
size = s + 1;
}
2.3.2 grow方法(核心方法)
private Object[] grow(int minCapacity) {
return elementData = Arrays.copyOf(elementData,
newCapacity(minCapacity));
}
private Object[] grow() {
return grow(size + 1);
}
private int newCapacity(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
// 每次在原来的基础上加上0.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity <= 0) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
return Math.max(DEFAULT_CAPACITY, minCapacity);
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return minCapacity;
}
return (newCapacity - MAX_ARRAY_SIZE <= 0)
? newCapacity
: hugeCapacity(minCapacity);
}
调用add方法的流程图如下:
2.3.1 remove()方法
// 删除指定值,如果是int类型参数,传参的时候要包装成Integer
public boolean remove(Object o) {
final Object[] es = elementData;
final int size = this.size;
int i = 0;
found: {
if (o == null) {
for (; i < size; i++)
if (es[i] == null)
break found;
} else {
for (; i < size; i++)
if (o.equals(es[i]))
break found;
}
return false;
}
fastRemove(es, i);
return true;
}
private void fastRemove(Object[] es, int i) {
modCount++;
final int newSize;
if ((newSize = size - 1) > i)
// es:原数组,i + 1 : 原数组起始位置
// es:目标数组,i : 目标数组其实位置
// newSize - i : 要复制的数组长度
System.arraycopy(es, i + 1, es, i, newSize - i);
es[size = newSize] = null;
}
// 删除指定位置元素
public E remove(int index) {
Objects.checkIndex(index, size);
final Object[] es = elementData;
@SuppressWarnings("unchecked") E oldValue = (E) es[index];
// 调用fastRemove方法
fastRemove(es, index);
return oldValue;
}
2.3.1 set()方法
public E set(int index, E element) {
// 检查下表是否合法
Objects.checkIndex(index, size);
// 更新前的值
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
2.3.2 indexOf()方法
public int indexOf(Object o) {
return indexOfRange(o, 0, size);
}
int indexOfRange(Object o, int start, int end) {
Object[] es = elementData;
// 判断是否为空,如果为空,返回第一个为空的下标
if (o == null) {
for (int i = start; i < end; i++) {
if (es[i] == null) {
return i;
}
}
} else {
for (int i = start; i < end; i++) {
if (o.equals(es[i])) {
return i;
}
}
}
// 没有找到,返回-1
return -1;
}
2.3.3 get()方法
public E get(int index) {
Objects.checkIndex(index, size);
return elementData(index);
}
E elementData(int index) {
return (E) elementData[index];
}