Análisis de código fuente ArrayList

Todo el análisis se basa en
la estructura de datos de JDK15 ArrayList es una matriz. Implementación basada en matrices. Es una estructura de datos insegura para subprocesos . Implementada la interfaz List.
Inserte la descripción de la imagen aquí

Explicación de atributos

	 //默认ArrayList的容量
	 private static final int DEFAULT_CAPACITY = 10;
     /** 空数组实例 */
     private static final Object[] EMPTY_ELEMENTDATA = {
    
    };
     /** 共享的空数组实例 */
     private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {
    
    };

     /** 数组元素数据 */
     transient Object[] elementData; 
     /** 数组元素个数 */
     private int size;

Constructor

ArrayList () construye una lista vacía con una capacidad inicial de 10.
ArrayList (int initialCapacity) Construye una lista vacía con la capacidad inicial especificada.
ArrayList (Colección <? Extiende E> c) Construye una lista que contiene los elementos de la colección especificada, cuyo orden es devuelto por el iterador de la colección.

API

1 booleano agregar (E e) agregar elemento

public boolean add(E e) {
    
    
        modCount++;
        add(e, elementData, size);
        return true;
}

modCount es una propiedad de AbstractList, la clase padre de ArrayList. El objetivo principal es no permitir modificaciones a la estructura de la colección cuando el iterador está iterando la colección. Si se realiza alguna modificación, se informará una excepción de modificación concurrente. Seguimiento detallado.
La adición de add se realiza en el método interno add (e, elementData, size) ;.

private void add(E e, Object[] elementData, int s) {
    
    
        if (s == elementData.length)
            elementData = grow();
        elementData[s] = e;
        size = s + 1;
    }

Si el número de elementos es igual a la longitud de la matriz, expanda la capacidad; de lo contrario, agregue elementos directamente. La longitud del elemento de la matriz es +1. Observa la implementación de la expansión y llama al método grow ().

private Object[] grow() {
    
    
        return grow(size + 1);
    }

También es privado y se implementa llamando a grow (int minCapacity) internamente. El parámetro es la capacidad actual + 1.

private Object[] grow(int minCapacity) {
    
    
		// 获取旧数组的长度
        int oldCapacity = elementData.length;
        //如果旧数组容量>0 或者不为空数组。就开始扩容
        if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
    
    
            int newCapacity = ArraysSupport.newLength(oldCapacity,
                    minCapacity - oldCapacity, /* minimum growth */
                    oldCapacity >> 1           /* preferred growth */);
            return elementData = Arrays.copyOf(elementData, newCapacity);
        } else {
    
    
            return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
        }
}

Si es una matriz vacía, devuelve la matriz con la capacidad mínima y la capacidad máxima predeterminada.

elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)

Nueva capacidad:

int newCapacity = ArraysSupport.newLength(oldCapacity,
                    minCapacity - oldCapacity, /* minimum growth */
                    oldCapacity >> 1

Llame al método ArraysSupport.newLength para lograr.

public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
    
    
        // assert oldLength >= 0
        // assert minGrowth > 0

        int newLength = Math.max(minGrowth, prefGrowth) + oldLength;
        if (newLength - MAX_ARRAY_LENGTH <= 0) {
    
    
            return newLength;
        }
        return hugeLength(oldLength, minGrowth);
    }

Aquí prefGrowth es la tasa de crecimiento preferida y minGrowth es la tasa de crecimiento mínima.
minGrowth = minCapacity-oldCapacity
prefGrowth = oldCapacity >> 1 = 0.5oldCapacity. Por lo tanto, la longitud expandida real es 1,5 veces la longitud original de la matriz. Finalmente, se copia la matriz.

elementData = Arrays.copyOf(elementData, newCapacity);

2 void add (int index, E element) Agrega el elemento a la posición especificada

public void add(int index, E element) {
    
    
		//检查索引是否超过数组长度
        rangeCheckForAdd(index);
        modCount++;
        final int s;
        Object[] elementData;
        if ((s = size) == (elementData = this.elementData).length)
            elementData = grow();
        System.arraycopy(elementData, index,
                         elementData, index + 1,
                         s - index);
        elementData[index] = element;
        size = s + 1;
    }

Primero verifique si el índice está fuera de los límites y luego juzgue si el número de elementos es igual a la longitud de la matriz, ingrese la lógica. Expansión, luego copie los datos antiguos y luego asigne operaciones.

3 booleano addAll (Colección <? Extiende E> c) agregar colección

public boolean addAll(Collection<? extends E> c) {
    
    
		//将集合转换为Object数组
        Object[] a = c.toArray();
        modCount++;
        int numNew = a.length;
        if (numNew == 0)
            return false;
        Object[] elementData;
        final int s;
        //如果添加元素的长度大于剩余数组的容量,开始扩容。然后复制数据
        if (numNew > (elementData = this.elementData).length - (s = size))
            elementData = grow(s + numNew);
        System.arraycopy(a, 0, elementData, s, numNew);
        size = s + numNew;
        return true;
    }

4 trimToSize () establece la capacidad actual de la matriz a la longitud del elemento

public void trimToSize() {
    
    
        modCount++;
        if (size < elementData.length) {
    
    
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size);
        }
    }

5 garantizar la capacidad (int minCapacity) garantizar la capacidad

Si la capacidad de ArrayList no es suficiente para contener todos los elementos actuales, establezca la nueva capacidad = newLength = Math.max (capacidad mínima: capacidad del arreglo anterior, capacidad del arreglo anterior / 2) + capacidad del arreglo anterior = 1,5 capacidad del arreglo anterior

public void ensureCapacity(int minCapacity) {
    
    
        if (minCapacity > elementData.length
            && !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
                 && minCapacity <= DEFAULT_CAPACITY)) {
    
    
            modCount++;
            grow(minCapacity);
        }
    }

6 tamaño () Obtiene el número de elementos de la matriz

public int size() {
    
    
      return size;
 }

7 isEmpty () Determina si está vacío

public boolean isEmpty() {
    
    
        return size == 0;
}

8 indexOfRange () para encontrar elementos

int indexOfRange(Object o, int start, int end) {
    
    
        Object[] es = elementData;
        //如果为空,正向遍历
        if (o == null) {
    
    
            for (int i = start; i < end; i++) {
    
    
                if (es[i] == null) {
    
    
                    return i;
                }
            }
        } else {
    
    
        //不为空,直接遍历
            for (int i = start; i < end; i++) {
    
    
                if (o.equals(es[i])) {
    
    
                    return i;
                }
            }
        }
        return -1;
    }

9 contiene determina si se debe incluir un elemento

public boolean contains(Object o) {
    
    
		//调用index()方法正向查找
        return indexOf(o) >= 0;
    }

10 indexOf () búsqueda hacia adelante

public int indexOf(Object o) {
    
    
        return indexOfRange(o, 0, size);
    }

11 lastIndexOf () búsqueda inversa

 public int lastIndexOf(Object o) {
    
    
        return lastIndexOfRange(o, 0, size);
    }

12 clon

public Object clone() {
    
    
        try {
    
    
        	//调用父类的克隆方法,克隆空的ArrayList实例
            ArrayList<?> v = (ArrayList<?>) super.clone();
            //复制数组,然后赋值
            v.elementData = Arrays.copyOf(elementData, size);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
    
    
            // this shouldn't happen, since we are Cloneable
            throw new InternalError(e);
        }
    }

13 Objeto [] toArray () convertido en una matriz

public Object[] toArray() {
    
    
        return Arrays.copyOf(elementData, size);
    }

14 get (int index) Obtiene el elemento

 public E get(int index) {
    
    
        Objects.checkIndex(index, size);
        return elementData(index);
    }

15 remove (int index) elimina el elemento en la posición especificada

public E remove(int index) {
    
    
        Objects.checkIndex(index, size);
        final Object[] es = elementData;

        @SuppressWarnings("unchecked") E oldValue = (E) es[index];
        fastRemove(es, index);

        return oldValue;
    }

Supongo que te gusta

Origin blog.csdn.net/GoSaint/article/details/113871542
Recomendado
Clasificación