ArrayList的数据结构
ArrayList是一种线性数据结构,底层是动态数组实现的,与java中的数组相比,它的容量可以动态添加。
ArrayList的类结构
public class ArrayListextends AbstractList implements List , RandomAccess, Cloneable, java.io.Serializable{ ......}
ArrayList的主要成员变量
//默认容量private static final int DEFAULT_CAPACITY = 10;private static final Object[] EMPTY_ELEMENTDATA = {};private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//ArrayList存储数据的数组transient Object[] elementData;//存储元素数目private int size;//默认最大容量数目private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;//protected transient int modCount = 0;
ArrayList的构造方法
public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); }}
ArrayList的主要方法
存:
boolean add(E e);
public boolean add(E e) { //根据当前下角标size+1和当前数组的容量,判断是否需要扩容,如果需要,扩容到1.5倍 ensureCapacityInternal(size + 1); // Increments modCount!! //将新元素加入数组中,下角标为size+1 elementData[size++] = e; return true;}private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //如果存储元素的数组为空,容量值为10和minCapacity中的较大者 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity);}private void ensureExplicitCapacity(int minCapacity) { //更新次数加一 modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) //如果minCapacity大于当前数组的长度,扩容 grow(minCapacity);}private void grow(int minCapacity) { //将当前数组的长度赋值给oldCapacity int oldCapacity = elementData.length; //新的容量值为原来的1.5倍 int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) //如果新容量值比minCapacity 值小,新容量值即为minCapacity newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) //如果新容量值大于允许的最大长度 newCapacity = hugeCapacity(minCapacity); //根据容量创建一个新数组,并将旧数组的元素复制给新数组 elementData = Arrays.copyOf(elementData, newCapacity);}private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow //如果minCapacity小于零,直接抛出OOM异常 throw new OutOfMemoryError(); //如果minCapacity大于最大数组容量,则返回Integer的最大值,否则返回 return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;}
void add(int index,E e);
public void add(int index, E element) { //校验下角标index是否越界 rangeCheckForAdd(index); //判断是否需要扩容 ensureCapacityInternal(size + 1); // Increments modCount!! //将当前数组中下角标为[index,size]的元素复制到[index+1,size+1]的位置 System.arraycopy(elementData, index, elementData, index + 1, size - index); //将element放置到数组下角标为index的位置 elementData[index] = element; //数组内元素个数加1 size++;}private void rangeCheckForAdd(int index) { if (index > size || index < 0) //如果index大于数组元素的个数,或者index<0,抛出下角标越界异常 throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}
E set(int index,E e);
public E set(int index, E element) { //校验下角标是否越界 rangeCheck(index); //将数组中下角标为index的元素赋值给oldValue E oldValue = elementData(index); //再将新元素放置到下角标index位置 elementData[index] = element; //返回旧值 return oldValue;}
取:
E get(int index);
public E get(int index) { //校验下角标是否越界 rangeCheck(index); //返回数组中下角标为index的元素 return elementData(index);}private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}
移除:
E remove(int index);通过下角标移除。
public E remove(int index) { //判断下角标是否越界 rangeCheck(index); //修改次数加一 modCount++; //将数组中下角标为index的元素赋值给oldValue E oldValue = elementData(index); //要移动的元素个数 int numMoved = size - index - 1; if (numMoved > 0) //如果要移动的元素个数大于0,移动 // 将elementData数组index+1位置开始拷贝到elementData从index开始的空间 System.arraycopy(elementData, index+1, elementData, index, numMoved); //最后一个元素设为null,并将size-1 elementData[--size] = null; // clear to let GC do its work 返回旧值 return oldValue;}
boolean remove(Object o);移除指定元素
public boolean remove(Object o) { if (o == null) { //如果要移除的元素为null //循环遍历数组 for (int index = 0; index < size; index++) if (elementData[index] == null) { //如果某个下角标的元素为null //移除该下角标的元素 fastRemove(index); return true; } } else { //循环遍历数组 for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { //如果某个下角标的元素为o 移除该下角标的元素 fastRemove(index); return true; } } return false;}private void fastRemove(int index) { //修改次数加一 modCount++; //要移动的元素个数 int numMoved = size - index - 1; if (numMoved > 0) // 将elementData数组index+1位置开始拷贝到elementData从index开始的空间 System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work}