您的位置:首页 > 其它

1.7版本 Arraylist源码解读

2017-09-19 17:23 363 查看
1.7版本 Arraylist源码解读

分析一个类(对象)常用步骤:

1、属性:当前类具有的属性特征;

2、构造函数:在函数构造时完成了什么样的功能;

3、方法:具备什么样的功能;

4、内部类:辅助主类。

下面从这四个方面来对ArrayList类进行源码解读。

一、属性

1、默认容量

private static final int DEFAULT_CAPACITY = 10;


2、空数组

private static final Object[] EMPTY_ELEMENTDATA = {};


3、存放数据的数组,不可序列化

private transient Object[] elementData;


4、数组的大小

private int size;


二、构造函数

1、 无参构造函数

public ArrayList() {
super();
this.elementData = EMPTY_ELEMENTDATA;
}


2、有参构造函数-初始化容量参数

public ArrayList(int initialCapacity) {
super();
//初始化容量
if (initialCapacity < 0) {
//<0抛出不合法容量异常
throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
} else {
//>=0, 创建一个该容量大小的数组
this.elementData = new Object[initialCapacity];
}
}


3、有参构造函数-集合参数

public ArrayList(Collection<? extends E> c) {
//将集合转换为数组
elementData = c.toArray();
size = elementData.length;
if (elementData.getClass() != Object[].class)
//如果数组的类型不是Object,通过Arrays.copyOf方法将数据类型转化为Object
elementData = Arrays.copyOf(elementData, size, Object[].class);
}


三、方法

在这里,我们只介绍ArrayList扩容设计的精华部分:

1、trimToSize方法:优化内存

public void trimToSize() {
modCount++;
// 如果size小于length
if (size < elementData.length) {
// 重新将elementData设置大小为size
elementData = (size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size);
}
}


2、ensureCapacityInternal(int minCapacity):得到最小扩容量

private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
// 获取默认的容量和传入参数的较大值
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}


3、ensureExplicitCapacity(int minCapacity):判断是否需要扩容

private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// 如果最小需要空间比elementData的内存空间要大,则需要扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}


4、grow():扩容方法,扩容到原来的1.5倍

private void grow(int minCapacity) {
// 获取到ArrayList中elementData数组的内存空间长度
int oldCapacity = elementData.length;
// 扩容至原来的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 再判断一下新数组的容量够不够,够了就直接使用这个长度创建新数组,
// 不够就将数组长度设置为需要的长度
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 判断有没超过最大限制
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 调用Arrays.copyOf方法将elementData数组指向新的内存空间时newCapacity的连续空间
// 并将elementData的数据复制到新的内存空间
elementData = Arrays.copyOf(elementData, newCapacity);
}


四、内部类

(1)private class Itr implements Iterator<E>
(2)private class ListItr extends Itr implements ListIterator<E>
(3)private class SubList extends AbstractList<E> implements RandomAccess
(4)static final class ArrayListSpliterator<E> implements Spliterator<E>


ArrayList有四个内部类,

Itr:实现了Iterator接口,同时重写了里面的hasNext(),next(),remove()等方法;

ListItr:继承Itr,实现了ListIterator接口,同时重写了hasPrevious(),nextIndex(),previousIndex(),previous(),set(E e),add(E e)等方法,所以这也可以看出了Iterator和ListIterator的区别,就是ListIterator在Iterator的基础上增加了添加对象,修改对象,逆向遍历等方法,这些是Iterator不能实现的。

SubList:继承AbstractList,实现了RandmAccess接口,类内部实现了对子序列的增删改查等方法,但它同时也充分利用了内部类的优点,就是共享ArrayList的全局变量,例如检查器变量modCount,数组elementData等,所以SubList进行的增删改查操作都是对ArrayList的数组进行的,并没有创建新的数组。

最后一个内部类没怎么接触过,大家自行百度。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: