ArrayList集合原理
一、实现的接口
ArrayList集合实现接口:Serializable(序列号接口),Cloneable(克隆标记接口),Iterable(迭代器接口),Collection(集合根接口),List(List集合接口),RandomAccess(标记接口,作用为支持快速随机访问)
二、直接子类
AttributeList,RoleList,RoleUnresolvedList
三、ArrayList源码解读
-
创建ArrayList的三种方式
-
创建指定长度ArrayList
/** * Constructs an empty list with the specified initial capacity. * * @param initialCapacity the initial capacity of the list * @throws IllegalArgumentException if the specified initial capacity * is negative */ public ArrayList(int initialCapacity) { // 当长度大于0时创建该长度的数组 if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; // 当长度等于0时创建默认长度数组 } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { // 否则抛出异常 throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } }
-
创建默认长度ArrayList
/** * Constructs an empty list with an initial capacity of ten. */ public ArrayList() { // 创建默认长度的数组 this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
-
创建指定元素ArrayList
/** * Constructs a list containing the elements of the specified * collection, in the order they are returned by the collection's * iterator. * * @param c the collection whose elements are to be placed into this list * @throws NullPointerException if the specified collection is null */ public ArrayList(Collection<? extends E> c) { // 将元素转换成数组 elementData = c.toArray(); // 当转换得到的数组长度不为0时 if ((size = elementData.length) != 0) { // c.toArray might (incorrectly) not return Object[] (see 6260652) // 这里要加上特殊情况,如果数组缓冲区elementData的元素个数大于0,并且类型 // 不是Object[]的,就要通过Arrays.copyOf()方法,来转化为Object[] if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // replace with empty array. // 否则创建默认空元素默认长度数组 this.elementData = EMPTY_ELEMENTDATA; } }
-
-
校验扩容长度是否超过MAX_ARRAY_SIZE(Integer.MAX_VALUE - 8 = 2147483639)的长度
// 该方法是用于查看扩容长度是否超过ArrayList里面的最大限制长度。如果超过则将该长度设置为 // Integer.MAX_VALUE(整数类型最大值)的长度 private static int hugeCapacity(int minCapacity) { // 校验值是否小于0,小于零报错内存溢出异常。 if (minCapacity < 0) // overflow throw new OutOfMemoryError(); // 待扩容的值大于阈值取整数类型最大值,否则取阈值 return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
-
ArrayList扩容方法
private void grow(int minCapacity) { // overflow-conscious code // 获取当前ArrayList长度 int oldCapacity = elementData.length; // 获取当前长度与当前长度一半长度之和 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: // 复制ArrayList,赋予新长度,并形成新数组 elementData = Arrays.copyOf(elementData, newCapacity); } /** * Increases the capacity of this {@code ArrayList} instance, if * necessary, to ensure that it can hold at least the number of elements * specified by the minimum capacity argument. * * @param minCapacity the desired minimum capacity */ public void ensureCapacity(int minCapacity) { // 校验扩容长度是否大于原list长度,判断原数组是否为null或者扩容长度是否小于默认长度 if (minCapacity > elementData.length && !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA && minCapacity <= DEFAULT_CAPACITY)) { modCount++; // 进行扩容 grow(minCapacity); } } /** * Returns a capacity at least as large as the given minimum capacity. * Returns the current capacity increased by 50% if that suffices. * Will not return a capacity greater than MAX_ARRAY_SIZE unless * the given minimum capacity is greater than MAX_ARRAY_SIZE. * * @param minCapacity the desired minimum capacity * @throws OutOfMemoryError if minCapacity is less than zero */ private int newCapacity(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity <= 0) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) return Math.max(DEFAULT_CAPACITY, minCapacity); if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return minCapacity; } return (newCapacity - MAX_ARRAY_SIZE <= 0) ? newCapacity : hugeCapacity(minCapacity); } private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
-
ArrayList添加元素方法
/** * Appends the specified element to the end of this list. * * @param e element to be appended to this list * @return <tt>true</tt> (as specified by {@link Collection#add}) */ public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } /** * Inserts the specified element at the specified position in this * list. Shifts the element currently at that position (if any) and * any subsequent elements to the right (adds one to their indices). * * @param index index at which the specified element is to be inserted * @param element element to be inserted * @throws IndexOutOfBoundsException {@inheritDoc} */ public void add(int index, E element) { rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!! // 将原数组的数据在index位置及后面数据后移一位 System.arraycopy(elementData, index, elementData, index + 1, size - index); // 将值赋予index位置 elementData[index] = element; // ArrayList长度加一 size++; } /** * A version of rangeCheck used by add and addAll. */ // 校验指定位置添加数据时,指定位置是否存在 private void rangeCheckForAdd(int index) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }
-
ArrayList删除数据
/** * Removes the element at the specified position in this list. * Shifts any subsequent elements to the left (subtracts one from their * indices). * * @param index the index of the element to be removed * @return the element that was removed from the list * @throws IndexOutOfBoundsException {@inheritDoc} */ public E remove(int index) { // 校验指针是否超过ArrayList长度 rangeCheck(index); modCount++; // 取出对应的值 E oldValue = elementData(index); // 获取待删除索引的后面值个数 int numMoved = size - index - 1; // 当numMoved大于0时,将后面数据前移一位 if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); // 长度减小,并将原长度最后一位置空 elementData[--size] = null; // clear to let GC do its work // 返回删除数据 return oldValue; } /** * Removes the first occurrence of the specified element from this list, * if it is present. If the list does not contain the element, it is * unchanged. More formally, removes the element with the lowest index * <tt>i</tt> such that * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt> * (if such an element exists). Returns <tt>true</tt> if this list * contained the specified element (or equivalently, if this list * changed as a result of the call). * * @param o element to be removed from this list, if present * @return <tt>true</tt> if this list contained the specified element */ 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 remove method that skips bounds checking and does not * return the value removed. */ 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 }