首页 > 代码库 > ArrayList源码分析
ArrayList源码分析
1.ArrayList的特点:
线程不安全
查找速度快
增删速度慢
数组结构
ArrayList源码分析:
2.ArrayList的继承和实现接口关系
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
可以看到ArrayList继承了AbstractList<E>类,实现了implements List<E>, RandomAccess, Cloneable, java.io.Serializable接口;
AbstractList<E>类的继承实现关系如下了public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> ,AbstractList<E>继承了AbstractCollection类,查看AbstractList<E>类的源码,我们可以发现
AbstractList<E>实现了部分的方法,又有一部分的方法是抽象的方法;
当我们看AbstractCollection<E> 源码的时候,可以发现public abstract class AbstractCollection<E> implements Collection<E>,终于AbstractCollection<E> 实现了Collection<E>接口,ArrayList和Collection<E>终于挂上关系了,
AbstractCollection<E> 也实现了部分方法,有部分方法是抽象方法。
从这么多继承和实现关系,可以看出这些类的实现都是分层的,那个类做什么事情。
由于ArrayList类的方法众多,我就不每个都介绍了,下面主要介绍下常用的方法和属性。想理解更多地可以直接看源代码,有很清楚的介绍
3.ArrayList的基本属性
private static final long serialVersionUID = 8683452581122892189L;//序列化的标志
private static final int DEFAULT_CAPACITY = 10;//Default initial capacity.即默认初始化的ArrayList的大小
private static final Object[] EMPTY_ELEMENTDATA = http://www.mamicode.com/{};//共享空数组实例用于空实例
private transient Object[] elementData;//数组缓冲区存储数组列表的元素,存储元素的数组
private int size;//数组元素的大小
4.ArrayList的构造方法
初始化指定大小的列表,初始化大小为initialCapacity,如果参数小于0则会抛出参数非法异常,如果参数大于0,则创建指定大小的Object数组,使elementData元素指向数组
public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = http://www.mamicode.com/new Object[initialCapacity];>
初始化ArrayList里面的elementData,利用一个空的Object数组初始化EMPTY_ELEMENTDATA
public ArrayList() { super(); this.elementData = http://www.mamicode.com/EMPTY_ELEMENTDATA;>
使用指定的集合初始化列表,列表的长度就是集合元素c的长度,及集合c的数据元素的个数
public ArrayList(Collection<? extends E> c) {
elementData = http://www.mamicode.com/c.toArray();
size = elementData.length;
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = http://www.mamicode.com/Arrays.copyOf(elementData, size, Object[].class);
}
elementData = http://www.mamicode.com/Arrays.copyOf(elementData, size, Object[].class);//这一句是进行数组的复制
5.ArrayList常用的方法
//将此 ArrayList 实例的容量调整为列表的当前大小,去掉列表中多余的空间, public void trimToSize() { modCount++; if (size < elementData.length) {//如果目前的元素个数小于elementData的空间个数,即有多余的空间浪费了没有使用 elementData = http://www.mamicode.com/Arrays.copyOf(elementData, size);//进行数组的复制,去掉多余的空间>//如果有必要的话,增加列表空间的大小,确保列表能够存放下元素 public void ensureCapacity(int minCapacity) { //最小的扩张列表的大小 int minExpand = (elementData != EMPTY_ELEMENTDATA)//如果elementData不等于EMPTY_ELEMENTDATA // any size if real element table ? 0 // larger than default for empty table. It's already supposed to be // at default size. : DEFAULT_CAPACITY;//默认的大小及定义的10 //如果最小的空间长度大于最小规定的扩展长度则进行扩展 if (minCapacity > minExpand) { ensureExplicitCapacity(minCapacity); } }
进行列表的扩容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 = http://www.mamicode.com/Arrays.copyOf(elementData, newCapacity);>返回列表元素的长度
public int size() { return size; }判断是否为空
public boolean isEmpty() { return size == 0; }
//从前到后依次查找元素在集合中第一次出现的下标,如果找到了则返回下标,没有则返回-1 public int indexOf(Object o) { if (o == null) {//如果元素为null for (int i = 0; i < size; i++) if (elementData[i]==null)//如果列表中存在为null的元素,则返回下标 return i;//返回下标 } else {//如果元素o不为null for (int i = 0; i < size; i++)//进行顺序查找 if (o.equals(elementData[i]))//进行判断,如果存在相等,则返回下标i return i;//返回下标 } return -1;//没有查找到,则返回-1 }//进行判断,元素o是否存在于列表中 public boolean contains(Object o) { //如果查找到了,则返回true,没有查找到则返回false return indexOf(o) >= 0;//返回结果 }
//从后向前依次查找元素在集合中第一次出现的下标,如果找到了则返回下标,没有则返回-1 public int lastIndexOf(Object o) { if (o == null) {//如果元素为null for (int i = size-1; i >= 0; i--) if (elementData[i]==null)//如果列表中存在为null的元素,则返回下标 return i;//返回下标 } else { for (int i = size-1; i >= 0; i--)//进行顺序查找 if (o.equals(elementData[i]))//进行判断,如果存在相等,则返回下标i return i;//返回下标 } return -1;//没有查找到,则返回-1 }
//把列表转换成数组进行返回 public Object[] toArray() { return Arrays.copyOf(elementData, size);//数组进行复制,返回复制后的数组 }//返回集合中包含的数组a的所有元素 public <T> T[] toArray(T[] a) { if (a.length < size)//如果数组a长度小于列表的长度,则直接把列表前size个元素复制给a数组 // Make a new array of a's runtime type, but my contents: return (T[]) Arrays.copyOf(elementData, size, a.getClass());//返回复制后的结果 System.arraycopy(elementData, 0, a, 0, size);//如果数组a的长度大于列表的长度,则把列表从0到size的元素复制给a数组 if (a.length > size)//如果a的长度大于size,则a数组有值的最后一个空的空间置位null a[size] = null; return a;//返回a数组 }//得到指定位置的元素 public E get(int index) { rangeCheck(index);//进行参数的检查,看是否在可控的范围内 return elementData(index);//返回指定下标的元素 }//把更改指定位置的值 public E set(int index, E element) { rangeCheck(index);//进行参数的检查 E oldValue = http://www.mamicode.com/elementData(index);//得到改变前指定位置的元素>//在列表的末尾添加元素 public boolean add(E e) { //进行空间的检查,看空间是否够存入新的元素,不够的话进行分配新的空间 ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e;//把元素放到列表的最后,元素的个数size加1 return true;//元素添加成功后,返回true }//在指定的位置插入元素 public void add(int index, E element) { rangeCheckForAdd(index);//检查参数index范围 //确保空间足够添加元素 ensureCapacityInternal(size + 1); // Increments modCount!! //进行数组元素的复制操作,把index以后的所有元素往后移动一个位置 System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element;//在index位置插入元素element size++;//列表元素的个数加1 }//删除指定位置的元素 public E remove(int index) { rangeCheck(index);//参数检查 modCount++; E oldValue = http://www.mamicode.com/elementData(index);//得到删除前指定位置的元素>
//删除指定的元素o public boolean remove(Object o) { if (o == null) {//如果元素o为空 for (int index = 0; index < size; index++)//顺序查找是否存在为null的元素 if (elementData[index] == null) {//如果为null fastRemove(index);//进行快速删除 return true;//返回结果 } } else {//如果元素o不为空 for (int index = 0; index < size; index++)//进行查找 if (o.equals(elementData[index])) {//如果找到了与元素o相等的元素 fastRemove(index);进行快速删除 return true;//返回结果true } } return false;//返回结果false }
//私有的方法,进行快速的删除操作,删除指定的位置元素index private void fastRemove(int index) { modCount++; int numMoved = size - index - 1;//需要移动元素的长度 if (numMoved > 0)//如果移动的长度数量大于0 System.arraycopy(elementData, index+1, elementData, index, numMoved);//进行移动复制 //元素数量减一,最后一个元素置为null elementData[--size] = null; // clear to let GC do its work }
//清空列表中所有的元索 public void clear() { modCount++; // clear to let GC do its work for (int i = 0; i < size; i++)//进行循环,把所有的元素置位null elementData[i] = null;//把元素置位null size = 0;//列表的大小置位0 }
//把一个集合的元素添加到列表中 public boolean addAll(Collection<? extends E> c) { Object[] a = c.toArray();//把集合转换成Object数组 int numNew = a.length;//得到Object数组的大小 //看是否需要开辟空间,需要则进行开辟新的空间 ensureCapacityInternal(size + numNew); // Increments modCount System.arraycopy(a, 0, elementData, size, numNew);//进行数组的复制 size += numNew;//列表元素的长度变了 return numNew != 0;//添加完成以后的返回值 }
//从指定的位置开始,把一个集合添加到列表中 public boolean addAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index);//index下标检查 Object[] a = c.toArray();//转换成数组 int numNew = a.length;//得到长度 //开辟空间 ensureCapacityInternal(size + numNew); // Increments modCount int numMoved = size - index;//得到需要移动的长度 if (numMoved > 0)//如果移动的长度大于0 System.arraycopy(elementData, index, elementData, index + numNew, numMoved);//进行数组移动的复制 System.arraycopy(a, 0, elementData, index, numNew);//数组的复制 size += numNew;//列表元素长度增加 return numNew != 0;//返回添加的结果 }//删除列表中指定范围的元素 protected void removeRange(int fromIndex, int toIndex) { modCount++; int numMoved = size - toIndex; System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved);//进行复制 // clear to let GC do its work int newSize = size - (toIndex-fromIndex); for (int i = newSize; i < size; i++) { elementData[i] = null;//置位null } size = newSize;//列表中新的元素的长度 }