系统环境: JDK 1.7
成员变量
//默认的初始化数组大小 private static final int DEFAULT_CAPACITY = 10; //空的对象数组 private static final Object[] EMPTY_ELEMENTDATA = {}; //声明对象数组,不可序列化 transient private transient Object[] elementData; //数组的大小 private int size;
构造方法
1.带有容量initialCapacity的构造方法
public ArrayList(int initialCapacity) { super(); //参数小于0 则抛出异常 if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); //new一个该大小的object数组赋给elementData this.elementData = new Object[initialCapacity]; }
2.不带参数的构造方法
public ArrayList() { super(); this.elementData = EMPTY_ELEMENTDATA; }
3.带参数Collection的构造方法
public ArrayList(Collection<? extends E> c) { //将 c 转换为对象数据并赋值给elementData elementData = c.toArray(); //获取数组大小 size = elementData.length; // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } 注:c.toArray()返回的类型可能是非Object[]类型,如:Arrays.asList().toArray(),详情参考《关于 ArrayList.toArray()和Arrays.asList().toArray()方法》
总结:通过三个构造方法 我们发现ArrayList的实质就是封装了对数组的一些操作,通过这些操作,从而达到我们需要的目的
Add方法分析
public boolean add(E e) { // 确保当前的数组大小可以装的下传入的对象e ensureCapacityInternal(size + 1); // Increments modCount!! // 在内部数组中存放对象,并将索引值+1 elementData[size++] = e; return true; } public void add(int index, E element) { // 确保传入的数值没有越界 rangeCheckForAdd(index); // 确保当前的数组大小可以装的下传入的对象e ensureCapacityInternal(size + 1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } private void ensureCapacityInternal(int minCapacity) { //针对new ArrayList()这种初始化方法有效,只有无参构造方法让内部数组等于empty。 if (elementData == EMPTY_ELEMENTDATA) { // 确保 minCapacity 最小值是 10 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } // ensureExplicitCapacity(minCapacity); } //判断是不是真的需要扩容。 //如果我们用new ArrayList()初始化,根据上边的代码 minCapacity=10,而现在内部类真正的大小elementData.length是 0,所以需要扩容。 //如果我们用new ArrayList(20)初始化,内部数组在构造方法内已经初始化了,内部数组长度为20,而在add方法的时候,第一个操作传入的是size+1,即0+1。 //所以到达这个判断的时候,最小需要的容量为1,而长度为20 ,必然不需要扩容 private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } //数组真正的扩容操作 private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; // 新长度为原数组长度的1.5倍 整数右移1为 相当于除2 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 = Arrays.copyOf(elementData, newCapacity); }
Remove方法分析
remove方法有2个,传入的参数分别是int和Object
public E remove(int index) { //判断传入的数字是否在合理范围内,即是否小于数组内真实的数据个数 rangeCheck(index); modCount++; E oldValue = elementData(index);//将要remove的索引位置的元素取出 //将内部数组中空出来的那个位置之后的元素移动到前边去 int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); // 将最后一位置空,size自减 elementData[--size] = null; // clear to let GC do its work return oldValue; // 返回移除的那个数据 } //另一个重载方法,实质上是一样的 public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } //移除数据操作 private void fastRemove(int index) { modCount++; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work } //判断传入的数字是否在合理范围内 private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } @SuppressWarnings("unchecked") E elementData(int index) { return (E) elementData[index]; }
System.arraycopy()方法
*5个参数的含义分别是:
--src 源数组.
--srcPos 源数组中的起始位置。
--dest 目标数组。
--destPos 目标数据中的起始位置。
--length 要复制的数组元素的数目
int[] arr1 = { 0, 1, 2, 3, 4, 5 }; int[] arr2 = { 6, 7, 8, 9, 10, 11}; // 将arr1的元素复制到arr2中,从arr1的索引位置为3开始,复制长度为1个,到arr2中,arr2从索引为0的位置开始接受复制 System.arraycopy(arr1, 3, arr2, 0, 1); // 所以最后结果是-- arr1:{ 0, 1, 2, 3, 4, 5 } arr2:{ 3, 7, 8, 9, 10, 11} System.out.println(Arrays.toString(arr1)); System.out.println(Arrays.toString(arr2));
整理自《http://blog.csdn.net/zw0283/article/details/51122255》