1、ArrayList特点
ArrayList在数据结构中可以类比为一个数组,然而又与数组差别很大,最大的差别在ArrayList没有容量的限制(动态数组)。而数组在申明时就必须给定容量,且在接下来的使用中存放的数据个数不可以超过容量。其实ArrayList的底层实现也是一个数组,只不过他在实现的时候做了一些优化,从而突破List容量限制的功能
2、ArrayList源码分析
2、1数据结构与储存
//ArrayList默认的大小,大小为10
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//elementData为一个数组,用于存放ArrayList中的元素
transient Object[] elementData; // non-private to simplify nested class access
//当前数组elementData的大小
private int size;
2、2核心方法分析
2、2、1构造函数分析
无参构造函数
/**
* Constructs an empty list with an initial capacity of ten.
*/
//无参构造函数,将当前当前一个为空的DEFAULTCAPACITY_EMPTY_ELEMENTDATA赋值给elementData;
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
带容量参数的构造函数
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
//当initialCapacity参数合法时申请一个长度为initialCapacity的数组
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
//为空
this.elementData = EMPTY_ELEMENTDATA;
} else {
//参数非法
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
带集合的构造函数
/*
1、将集合转换为数组,并赋值给elementData
2、判断赋值后的elementData的长度
如果为0则进行以上函数initialCapacity为0的相同操作
如果不为0则调用数组的拷贝方法,将elementData重新分配内存单元,并进行赋值(类似C++的深拷贝)
*/
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
2、2、2重要方法分析
add方法:
add方法中最核心的为:
elementData = Arrays.copyOf(elementData, newCapacity);
//将elementData中的数值拷贝到长度为newCapacity的elementData(覆盖)中
/*
1、先确保当前的elementData有足够的空间去存放指定的泛型数据
2、在确保已经有足够的空间的条件下进行直接赋值操作
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
//计算elementData的容量
private static int calculateCapacity(Object[] elementData, int minCapacity) {
//当数组还没有分配内存空间的时候,返回默认设置的容量(默认容量为10)与指定容量的较大值
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
//如果不为空,返回minCapacity
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
//判断数组是否要进行自增长,当当前的容量超过最小容量时,数组要进行自增长
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
//自增长函数,将当前elementData的容量扩大1.5倍
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
get方法
//get方法
public E get(int index) {
//用于检测index下标是否已经越界
rangeCheck(index);
return elementData(index);
}
set方法
//set方法
public E set(int index, E element) {
//用于检测index下标是否已经越界
rangeCheck(index);
//保存旧值并设置新值
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
未完待续............
附:限于编者水平与能力,欢迎广大读者批评指正