1、进入Java的JDK ArrayList源码
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { private static final long serialVersionUID = 8683452581122892189L; /** * 默认大小为10 */ private static final int DEFAULT_CAPACITY = 10; /** * 数据存放在 */ transient Object[] elementData; // non-private to simplify nested class access //数字大小 private int size; ...... }
可以看出,ArrayList默认使用数组来存放数据
2、构造方法
//有初始容量 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); } } //空构造函数,默认为DEFAULTCAPACITY_EMPTY_ELEMENTDATA public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } //传入初始集合 public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // replace with empty array. this.elementData = EMPTY_ELEMENTDATA; } }
3、添加操作
//添加单个元素,详细在1)介绍 public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } //添加单个元素到某个位置. 详细在2)介绍 public void add(int index, E element) { rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } //添加集合元素 public boolean addAll(Collection<? extends E> c) { Object[] a = c.toArray(); int numNew = a.length; 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); Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // Increments modCount int numMoved = size - index; if (numMoved > 0) System.arraycopy(elementData, index, elementData, index + numNew, numMoved); System.arraycopy(a, 0, elementData, index, numNew); size += numNew; return numNew != 0; }
1) add(E e)
//添加单个元素 public boolean add(E e) { //1、扩容操作 ensureCapacityInternal(size + 1); // Increments modCount!! //2、设置数组尾元素为e elementData[size++] = e; return true; } //ensureCapacityInternal扩容 private void ensureCapacityInternal(int minCapacity) { //如果是空数组,则minCapacity为10和参数 minCapacity的最大值 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } //ensureExplicitCapacity private void ensureExplicitCapacity(int minCapacity) { modCount++; // 说明数组需要扩容 if (minCapacity - elementData.length > 0) grow(minCapacity); } //grow private void grow(int minCapacity) { //1、原数组大小 int oldCapacity = elementData.length; //2、新的数字大小: 扩到1.5倍 int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; //3、如果大于MAX_ARRAY_SIZE,MAX_ARRAY_SIZE值为Integer.MAX_VALUE - 8, // MAX_VALUE值为2的31次减1(2147483647) if (newCapacity - MAX_ARRAY_SIZE > 0) //设置最大容量 newCapacity = hugeCapacity(minCapacity); //4、 执行数字拷贝操作 elementData = Arrays.copyOf(elementData, newCapacity); } //设置最大容量,也就是Integer.MAX_VALUE,2147483647 private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
这里主要是一个扩容的操作,扩容的大小为数组长度的1.5倍。 默认构造函数没有初始化数组大小,在扩容这里增加数组大小。也就初始化长度是滞后的,这样比在构造函数里初始化数组大小更好,防止无用的ArrayList出现。
2) add(int index, E element)
public void add(int index, E element) { //1、校验index,如果index超过了size,则报错 rangeCheckForAdd(index); //2、扩容操作 ensureCapacityInternal(size + 1); // Increments modCount!! //3、数组拷贝 System.arraycopy(elementData, index, elementData, index + 1, size - index); //4、赋值 elementData[index] = element; size++; } //rangeCheckForAdd. 校验index private void rangeCheckForAdd(int index) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }
3、删除操作
// 1.删除某个索引处的元素 public E remove(int index) { } // 2.删除某个元素 public boolean remove(Object o) { } // 3.批量删除 public boolean removeAll(Collection<?> c) { } // 4.按照条件删除 @Override public boolean removeIf(Predicate<? super E> filter) { } // 5.全部删除 public void clear() { }
1)E remove(int index)
public E remove(int index) { //1、针对index进行边界检查 rangeCheck(index); modCount++; E oldValue = elementData(index); //2、获得需要挪动的元素长度 int numMoved = size - index - 1; //3、index之后的元素向前平移一位 if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); //4、最后一位元素值为null,已经是无效元素了。 elementData[--size] = null; // clear to let GC do its work return oldValue; }
2) remove(Object o)
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; }
从 remove(Object o)的源码可知,针对存在多个相同元素的ArrayList,则之后删除第一个元素。
4、修改操作
//修改操作 public E set(int index, E element) { rangeCheck(index); //1、获取到原来的元素 E oldValue = elementData(index); //2、直接替换 elementData[index] = element; return oldValue; }
5、查询操作
//根据索引获取元素值 public E get(int index) { rangeCheck(index); return elementData(index); } public int indexOf(Object o) { //如果对象为空,返回第一个为空的对象索引 if (o == null) { for (int i = 0; i < size; i++) if (elementData[i]==null) return i; } else { //如果对象不为空,返回第一个相等对象的索引 for (int i = 0; i < size; i++) if (o.equals(elementData[i])) return i; } return -1; } //数字从后往前进行查询 public int lastIndexOf(Object o) { if (o == null) { for (int i = size-1; i >= 0; i--) if (elementData[i]==null) return i; } else { for (int i = size-1; i >= 0; i--) if (o.equals(elementData[i])) return i; } return -1; }