java基础,集合,Arraylist,源码解析
ArrayList
- 是什么,定义?
这是动态的数组,它提供了动态的增加和减少元素,实现了List接口(List实现Collection,所以也实现Collection接口)灵活的设置数组的大小等好处
- 内部如何实现
1 /** 2 * The array buffer into which the elements of the ArrayList are stored. 3 * The capacity of the ArrayList is the length of this array buffer. 4 */ 5 private transient Object[] elementData;//内部是数组 6 7 /** 8 * The size of the ArrayList (the number of elements it contains). 9 * 10 * @serial 11 */ 12 private int size;//定义大小 13 14 /** 15 * Constructs an empty list with the specified initial capacity. 16 * 17 * @param initialCapacity the initial capacity of the list 18 * @throws IllegalArgumentException if the specified initial capacity 19 * is negative 20 */ 21 public ArrayList(int initialCapacity) {//带参数的初始化 22 super(); 23 if (initialCapacity < 0) 24 throw new IllegalArgumentException("Illegal Capacity: "+ 25 initialCapacity); 26 this.elementData = new Object[initialCapacity]; 27 } 28 29 /** 30 * Constructs an empty list with an initial capacity of ten. 31 */ 32 public ArrayList() {//默认初始化,大小是10 33 this(10); 34 }
- 添加如何操作
1 public boolean add(E e) { 2 ensureCapacityInternal(size + 1); // 进行长度的判断与修改(将检查与扩容放在一个方法调用,代码阅读性高) 3 elementData[size++] = e; 4 return true; 5 } 6 7 private void ensureCapacityInternal(int minCapacity) { 8 modCount++; 9 // overflow-conscious code 10 if (minCapacity - elementData.length > 0)//进行判断 11 grow(minCapacity); 12 } 13 14 private void grow(int minCapacity) { 15 // overflow-conscious code 16 int oldCapacity = elementData.length; 17 int newCapacity = oldCapacity + (oldCapacity >> 1);//扩大原来的二分之一 18 if (newCapacity - minCapacity < 0)//最小的长度 19 newCapacity = minCapacity; 20 if (newCapacity - MAX_ARRAY_SIZE > 0)//最大长度 21 newCapacity = hugeCapacity(minCapacity); 22 // minCapacity is usually close to size, so this is a win: 23 elementData = Arrays.copyOf(elementData, newCapacity); 24 }
- 添加重要的一部,扩容,——这是为什么实际应用中要定义数组大小的原因,
1 //Array的源代码 2 public static <T> T[] copyOf(T[] original, int newLength) { 3 return (T[]) copyOf(original, newLength, original.getClass()); 4 } 5 6 public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {//需要复制原来的数组 7 T[] copy = ((Object)newType == (Object)Object[].class) 8 ? (T[]) new Object[newLength] 9 : (T[]) Array.newInstance(newType.getComponentType(), newLength); 10 System.arraycopy(original, 0, copy, 0, 11 Math.min(original.length, newLength)); 12 return copy; 13 }
- 制定位置的添加
1 public void add(int index, E element) { 2 rangeCheckForAdd(index); 3 4 ensureCapacityInternal(size + 1); // Increments modCount!! 5 System.arraycopy(elementData, index, elementData, index + 1, 6 size - index);//仅仅是当前位置以后的对象进行复制 7 elementData[index] = element; 8 size++; 9 }
- 删除对象
public E remove(int index) { rangeCheck(index); modCount++; E oldValue = elementData(index); int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved);//制定位置以后的对象,向前移动一位 elementData[--size] = null; // Let gc do its work return oldValue; }
- 怎么遍历呢?
数组,通过数组的脚标,遍历;
for each 因为实现Iterator,也可以使用迭代器
使用中改注意:
1、初始化最好定义都用的长度,避免Arrarlist内部复制的操作;
2、如果删除的,尽量从后往前删除
3、不是线程安全,全部代码中都没有synchronized ,
如果有需要,使用Vector,两者的区别3点(其他基本是一样):
线程安全,
多了方法indexOf,
扩容的打大小是:1倍
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);