您的位置:首页 > 其它

源码解读--ArrayList

2018-04-03 21:04 351 查看
对于开发人员来说,用的最多的就是数组,链表,Map和List,之前我写过一篇HashMap的源码解读,今天就来简单说说ArrayList的源码。
一.首先看看她的初始化方法:
第①种public ArrayList() { //无参的构造器,初始值是一个默认的空 DEFAULTCAPACITY_EMPTY_ELEMENTDATA ={}
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}第②种
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {  //如果值不为空
// c.toArray 可能返回的不是 Object[]
if (elementData.getClass() != Object[].class)  //
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// 如果为空无赋值空对象
this.elementData = EMPTY_ELEMENTDATA;
}
}
第③种public ArrayList(int initialCapacity) { //指定初始大小
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity]; //初始化对象数组,指定数组的大小为初始值
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else { //若果initialCapcity<0要抛出异常
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}二. 添加:public boolean add(E e) {
ensureCapacityInternal(size + 1); // 判断是否需要扩容
elementData[size++] = e; //添加一个元素
return true;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {  //如果为空对象,
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);  //minCapacity为0和DEFULT_CAPACITY(10)取最大值为10
}

ensureExplicitCapacity(minCapacity);   //校验容量
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;  //修改的值加1

// overflow-conscious code
if (minCapacity - elementData.length > 0)  //如果容量大于数组的长度句需要扩容
grow(minCapacity);
}
private void grow(int minCapacity) {  //扩容
// overflow-conscious code
int oldCapacity = elementData.length; //老表的大小
int newCapacity = oldCapacity + (oldCapacity >> 1);  //扩容1.5倍
if (newCapacity - minCapacity < 0)  //一般来说这里不会小于0
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0) //大于最大值,要进一步判断
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);  //用Arrays.copyOf赋值数组
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow  多线程修改这个list的长度小于0,要报错
throw new OutOfMemoryError();
return (minC
4000
apacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
到此,list的添加完毕,总结如下:
1.如果没有指定list的长度,初始一个空的数组

2.添加值的时候,list长度大于当前容量,就扩展1.5倍(默认长度是10),否则就正常添加
三. 获取值public E get(int index) {
rangeCheck(index); //校验一下索引值

return elementData(index);
}
private void rangeCheck(int index) {  //如果索引大于list的长度 抛出异常
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
E elementData(int index) {  //获取索引值
return (E) elementData[index];
}
四.删除值public E remove(int index) {
rangeCheck(index); //校验索引
modCount++; //修改记录数加1
E oldValue = elementData(index); //获取到索引的值
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,numMoved); //将获取的index位置值扣掉,后面的值,复制到index位置
elementData[--size] = null; // 将索引值赋值为空,便于gc
return oldValue;
}
public static native void arraycopy(Object src,  int  srcPos, //src 源数组   srcPos 原数组要赋值的起始位置
Object dest, int destPos,  // dest 目标数组   destPost 目标数组放置的起始位置
int length);  //lenth 复制的长度
到此,ArrayList增删查就完成了,不过里面有几点需要注意一下。
1.ArrayList初始化的时候,默认值是10,有可能就尽量执行list的大小,因为每次扩容都是1.5倍,长度越大,浪费越大。
2.ArrayList是线程不安全的,注意多线程问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ArrayList