ArrayList source code analysis
1.Arraylist()
Public Arraylist()
Initialize an empty Object [] {} array collection
2.ArrayList(int initialCapacity)
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); } }
1) . if the container input parameter is greater than 0, the elementdata (array) is directly initialized to the input parameter size
2) . if the container input parameter = 0, the elementdata (array) directly initializes the empty array {}
3) . in other cases, throw new illegalargumentexception ("illegalcapacity:" + initialCapacity)
3.ArrayList(Collection<? extends E> c)
public ArrayList(Collection<? extends E> c) { Object[] a = c.toArray(); if ((size = a.length) != 0) { if (c.getClass() == ArrayList.class) { elementData = a; } else { elementData = Arrays.copyOf(a, size, Object[].class); } } else { // replace with empty array. elementData = EMPTY_ELEMENTDATA; } }
1) . convert to Object [] array through c.toArray function
2) . initialize the set size to a.length. If the array length is not equal to 0, judge whether the array type is arraylist.class. If so, assign the set array to the parameter group
3) . be responsible for converting the contents of the array into an Object [] array through Arrays.copyof and assigning values
4) If the input parameter set is empty, the initialization array is empty
4.add(E e)
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }
- In the first line, ensureCapacityInternal expands the capacity of the array. size+1 is used to ensure that the new array can meet the requirements
- The second line is assigned
private void ensureExplicitCapacity(int minCapacity) { modCount++; #1 if (minCapacity - elementData.length > 0) #2 grow(minCapacity); #3 }
#1 modCount indicates the number of modifications
#2 judge whether the transmitted capacity is greater than the current capacity
#3. If the second row is satisfied, expand the capacity
private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; #1 int newCapacity = oldCapacity + (oldCapacity >> 1); #2 if (newCapacity - minCapacity < 0) #3 newCapacity = minCapacity; #4 if (newCapacity - MAX_ARRAY_SIZE > 0) #5 newCapacity = hugeCapacity(minCapacity); #6 // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); #7 }
#1 get the capacity of the original array
#2. Calculate the capacity of the new array = the capacity of the old array + the capacity of the old array by one bit to the right (equivalent to that the capacity of the new array is 1.5 times that of the old array)
#3. The capacity of the old array * 1.5 is less than the capacity of the new array
#4, the new array capacity is assigned to the incoming capacity
#5. If the new array exceeds the maximum array size (Integer.MAX_VALUE-8)
private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
#6. If greater than Integer.MAX_VALUE(), the array size is set to integer.max_ Value, otherwise set to MAX_ARRAY_SIZE(Integer.MAX_VALUE - 8)
#7. Create an array through Arrays.copy and return the assignment to the current array
Note:
Integer.MAX_VALUE - 8 java array is not a class and there is no corresponding class file, so the array is synthesized from the element type by the jvm, so the jvm needs to obtain it through arrayleng, so this 8 is specially used to store the length of the array
5.add(int index, E element)
public void add(int index, E element) { rangeCheckForAdd(index); #1 ensureCapacityInternal(size + 1); #2 // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index);#3 elementData[index] = element; #4 size++; #5 }
#1. Check whether the subscript has exceeded the length of the array
#2. Expand the capacity if necessary
#3 take the incoming node as the starting point, and all subsequent nodes move back one bit
#4 assignment
#5 capacity + 1
private void rangeCheckForAdd(int index) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }
6.set(int index, E element)
public E set(int index, E element) { rangeCheck(index); E oldValue = elementData(index); elementData[index] = element; return oldValue; }
This method is relatively simple. It is mainly used to check whether the subscript is out of bounds and assign a value to the specified array position
7.get(int index)
public E get(int index) {
rangeCheck(index); return elementData(index); }
This method is relatively simple. It mainly checks the subscript first, obtains the value corresponding to the array according to the subscript, obtains the data, and then forcibly converts the type
8.remove(int index)
public E remove(int index) { rangeCheck(index); #1 modCount++; E oldValue = elementData(index); #2 int numMoved = size - index - 1; #3 if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); #4 elementData[--size] = null; #5 // clear to let GC do its work return oldValue; #6 }
#1. Verify that the incoming value is compared with the number of non empty data in the array. If the incoming data > = the number of array elements, an array index boundary exception is reported (throw new indexOutOfBoundsException)
#2. Get the value of index bit
#3 calculate how many digit group elements need to be moved
#4 if the number of bits to be moved is > 0, copy the original array from the index+1 bit to the numMoved bit and overwrite the original index bit
#5 assign the last bit of the element to null (remove the reference and help the virtual machine with garbage collection)
#6 return the deleted element