The core point of the underlying implementation of ArrayList
1. The collection bottom layer is implemented by using array
2. Why can a set store infinite size? ####The implementation of array expansion technology
Arrays.copyOf:
To copy the array, return the copied array. Parameters are the copied array and the copied length.
Return a new array. Expand the length of the original array to 2, and expand it to 10. The original data remains the same.
Code example implementation:
package com.mmall.demo2.demotest; import java.util.Arrays; public class Test001 { public static void main(String[] args) { Object[] objects = {1, 2}; System.out.println("Original array length" + objects.length); // Return a new array. Expand the length of the original array to 2, and expand it to 10. The original data remains the same. Object[] objects2 = Arrays.copyOf(objects, 10); System.out.println("Length of new array" + objects2.length); } }
Operation result:
System.arraycopy method:
If the array is relatively large, then using System.arraycopy will have advantages, because it uses memory replication, which saves a lot of time such as array addressing and access
Parameter explanation:
System.arraycopy(src,srcPos,dets,destPos, length);
src: source array;
srcPos: the starting position of the source array to be copied; - where to start copying from the original array. The subscript starts at 0.
dest: destination array;
destPos: the starting position where the destination array is placed; -- starting from where the destination array is placed. The subscript starts at 0.
Length: the length of the copy. --The length of the array to copy. Be careful not to cross the border when using.
Example code:
int[] fun ={0,1,2,3,4,5,6}; // src: source array; // srcPos: the starting position of the source array to be copied; -- where to start copying from the original array. // dest: destination array; // destPos: the starting position where the destination array is placed; -- starting from where the destination array is placed. // Length: the length of the copy. --Length of array to copy System.arraycopy(fun,0,fun,3,3); for (int i : fun) { System.out.print(i); }
The operation result is:
Error example code:
The length of the copy is 7: an array out of bounds error will be reported. Because its position starts from subscript 3, there are only four positions from the original array data of fun, position subscript 3 to the last subscript position. So the maximum length is 4.
Analyzing the source code of JDK1.8ArrayList collection
After jdk 1.7, the array default data size code is stored in the add method.
In jdk1.6, the default constructor initializes the elementData size.
Implementation of Arraylist based on array
- Construction method resolution.
Default construction method:
//(in jdk1.6, the default constructor initializes the elementData size) //The constructor knows that jdk1.7 does not initialize the size in the constructor. private Object[] elementData; //Default constructor public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
Construction method with parameters:
public ArrayList(int initialCapacity) { if (initialCapacity > 0) { //If the parameter is greater than 2, initialize the array and assign the array capacity this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { //Cannot be less than 0 otherwise an exception is thrown. throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } }
- add(index) resolution:
The default initialization size of the underlying array of Arraylist is 10 object arrays (jdk1.7 is initialized in the add method.)
private static final int DEFAULT_CAPACITY = 10;
public boolean add(E e) { //size the actual arrayList length. ensureCapacityInternal(size + 1); //Assign using Subscripts elementData[size++] = e; return true; }
Code resolution:
//Determine whether it is an empty array
//Compare the size, take the maximum value, default menu capacity default size 10, minCapacity is 1 for the first time
private void ensureCapacityInternal(int minCapacity) { //Determine whether it is an empty array if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //Compare the size, take the maximum value, default menu capacity default size 10, minCapacity is 1 for the first time minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } //Expand the capacity of the array. ensureExplicitCapacity(minCapacity); }
private void ensureExplicitCapacity(int minCapacity) { modCount++; //Whether the actual existing capacity (10 by default) is greater than the length of elementData storage. if (minCapacity - elementData.length > 0) grow(minCapacity); }
If the length of the array is greater than the length of the current array after the element is added, the capacity will be expanded, and the length of the array will be increased by half of the original array. Each expansion is 1.5 times.
//Expand 1.5 times the original capacity, for example, the original capacity is 2, 2 + 2 / 2 = 3
int newCapacity = oldCapacity + (oldCapacity >> 1);
// Increase array space private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; // 1.5 times capacity expansion based on the original capacity int newCapacity = oldCapacity + (oldCapacity >> 1) //Judge whether it is less than minCapacity after 1.5 times of capacity expansion if (newCapacity - minCapacity < 0) // Minimum guaranteed capacity is the same as minCapacity newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) // Maximum capacity cannot be exceeded newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData, newCapacity);
get(index) resolution:
public E get(int index) { //Judge whether the index is greater than or equal to size (elementData.length) by exceeding the boundary rangeCheck(index); return elementData(index); }
Transboundary judgment
private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }
remove(index) analysis according to index:
Source code:
public E remove(int index) { //Cross boundary inspection rangeCheck(index); modCount++; //Get value from subscript E oldValue = elementData(index); //Calculate the length after the deleted element (size=elementData.length) int numMoved = size - index - 1; if (numMoved > 0) //The following elements are overwritten one by one, starting with the deleted elements. System.arraycopy(elementData, index+1, elementData, index,numMoved); //Last element is null elementData[--size] = null; // clear to let GC do its work return oldValue; }
Example of removing arrayList values
Suppose subscript 2 is deleted and the content is the value of c
Array changes after deletion.
//Last element is null elementData[--size] = null; // clear to let GC do its work
//Calculates the length after the deleted element.
//Calculate the length after the deleted element int numMoved = size - index - 1;
//The following elements are overwritten one by one, starting with the deleted elements.
index+1 start copy value start position
index is replaced from there
The length of the value to be copied by numMoved.
//The following elements are overwritten one by one, starting with the deleted elements. System.arraycopy(elementData, index+1, elementData, index,numMoved);
remove(obj) parsing based on objects:
Source code:
public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { //Loop through, take out the value and compare. for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { //Delete by subscript fastRemove(index); return true; } } return false; }
Delete according to subscript (source code)
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 }
It can be seen from the source code that the efficiency of deleting based on the value is the lowest, but if the same value exists, the first one will be deleted, and the second one will not be deleted.
add(index,obj) resolution:
Source code
public void add(int index, E element) { //1. Cross boundary judgment rangeCheckForAdd(index); //2.elementData capacity initialization and capacity expansion ensureCapacityInternal(size + 1); // Increments modCount!! // System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; }
Implementation schematic diagram:
Process 1
Process 2
Process 2
//index start of subscript to insert, //index + 1 starts from the element after the subscript value to be inserted, //size - index length; the length of the element after the subscript to be inserted System.arraycopy(elementData, index, elementData, index + 1, size - index);
Vector bottom floor
Vector is thread safe, but its performance is lower than ArrayList.
The main differences between ArrayList and Vector are as follows:
(1) : Vector is thread safe. There are many synchronized in the source code, but ArrayList is not. As a result, Vector efficiency cannot be compared with ArrayList;
public synchronized boolean add(E e) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true; }
(2) : both ArrayList and Vector use linear continuous storage space. When the storage space is insufficient, ArrayList will increase by default by 50% and Vector by 2 times;
Source code of Vector expansion:
private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData, newCapacity); }
capacityIncrement defaults to 0, the default constructor. Therefore, Vector is increased by default by 2 times;
(3) : Vector can set capacityIncrement, but ArrayList can't. literally, it is the parameter of capacity, Increment and capacity growth.