前面记录了ArrayList的构造方法,现在记录一下ArrayList的重点方法的学习。
ArrayList用的最多的两个方法我赌5毛是add和get方法。
public boolean add(E e) { ensureCapacityInternal(size + 1);//检查elementData数组的容量是否需要扩容 elementData[size++] = e; return true; }
先检测一下数组elementData是否需要扩容,如果需要就扩容,检测完就将e对象加入elementData。接下来就进入扩容检测方法。
private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { // 判断元素数组是否为空数组 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); //比较取较大的一方作为扩容的目标容量 } ensureExplicitCapacity(minCapacity);//检查elementData数组的容量是否需要扩容 }
elementData如果等于DEFAULTCAPACITY_EMPTY_ELEMENTDATA,minCapacity变为DEFAULT_CAPACITY或者minCapacity较大的一方,并传入ensureExplicitCapacity方法。
private void ensureExplicitCapacity(int minCapacity) { modCount++;//结构性修改加1(可以参考:http://www.cnblogs.com/liuling/p/2013-8-21-04.html) if (minCapacity - elementData.length > 0)//如果目标容量比当前数组的容量要大则进行扩容操作 grow(minCapacity);//扩容操作 }
因为ArrayList是非线程安全的,所以声明了一个modCount对象。
大概意思就是说:在使用迭代器遍历的时候,用来检查列表中的元素是否发生结构性变化(列表元素数量发生改变)了,主要在多线程环境下需要使用,防止一个线程正在迭代遍历,另一个线程修改了这个列表的结构。
如果目标容量比当前数组的容量要大则进行扩容方法grow。
private void grow(int minCapacity) { int oldCapacity = elementData.length; // 旧容量 int newCapacity = oldCapacity + (oldCapacity >> 1); // 新容量为旧容量的1.5倍 if (newCapacity - minCapacity < 0) // 新容量小于参数指定容量,修改新容量 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) // 当minCapacity等于Integer.MAX_ARRAY_SIZE+1的时候这个判断就会成立 抛出数组越界的错误。 throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
至此,最常用的add方法已经实现。然后就是get方法。
@Override public E get(int index) { if (index > size)//数组越界的情况 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); return (E) elementData[index]; }
最普遍的add方法和get方法至此已经实现。
public void add(int index, E element) { if (index > size || index < 0)//数组判断 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); ensureCapacityInternal(size + 1); // 扩容操作 System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; }
这个add一样,检查是否数组越界-->检查是否需要扩容-->将数组elementData[index]后面的所有数据从elementData[index+1]开始填充。
简单的例子:elementData={2,3,4,5,6} , index=0,element=1。
System.arraycopy(elementData, index, elementData, index + 1, 5);
-->elementData={0,2,3,4,5,6}//这里是扩容过的elementData
elementData[index] = element;
-->elementData={1,2,3,4,5,6}
get和add方法已经全部学习了,还有一个常用的方法 indexOf 有点复杂,放到下一篇记录。