源码解读--ArrayList
2018-04-03 21:04
351 查看
对于开发人员来说,用的最多的就是数组,链表,Map和List,之前我写过一篇HashMap的源码解读,今天就来简单说说ArrayList的源码。
一.首先看看她的初始化方法:
第①种public ArrayList() { //无参的构造器,初始值是一个默认的空 DEFAULTCAPACITY_EMPTY_ELEMENTDATA ={}
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}第②种
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;
}
1.如果没有指定list的长度,初始一个空的数组
2.添加值的时候,list长度大于当前容量,就扩展1.5倍(默认长度是10),否则就正常添加
三. 获取值public E get(int index) {
rangeCheck(index); //校验一下索引值
return elementData(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;
}
1.ArrayList初始化的时候,默认值是10,有可能就尽量执行list的大小,因为每次扩容都是1.5倍,长度越大,浪费越大。
2.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是线程不安全的,注意多线程问题。
相关文章推荐
- Java源码解读之util.ArrayList
- JAVA中ArrayList的扩增源码解读
- Java之ArrayList源码解读(JDK 1.8)
- Java源码解读之util.ArrayList .
- 集合框架(一):ArrayList源码解读
- java集合之ArrayList源码解读 帮助大家自己动手写一个ArrayList
- Java集合—ArrayList的源码解读
- jdk源码解读之ArrayList
- Java源码解读——ArrayList(二)
- Java源码解读-ArrayList
- Java源码解读——ArrayList
- Java 2源码解读:java.util.ArrayList
- 【源码解读】从ArrayList.class中解读为什么foreach中不能移除ArrayList元素
- ArrayList源码简略解读
- ArrayList源码解读
- ArrayList源码解读
- 1.7版本 Arraylist源码解读
- ArrayList源码解读
- Java 2源码解读:java.util.ArrayList (转)
- Java源码解读之util.ArrayList