análisis de código fuente Hardcore ArrayList, que se comprometió a repasar lo que un buen día

Un prólogo

buscadores de conocimiento se basan en el análisis de aprendizaje serie jdk1.8 actual; análisis de código fuente Benpian se llevará a cabo todos los análisis de paso, cuando se analizarán todos los métodos después de la última gran suma; Si no lo hace como etapa de análisis de código fuente, siempre y cuando la entrevista final los lectores pueden ver el resumen de las conclusiones al final del texto en la línea;

El conocimiento Seeker (Heredar el espíritu de código abierto, Difusión del conocimiento tecnológico;)

análisis de código fuente Dos ArrayList

análisis de la fuente constructor nula 2.2 Referencia

código de depuración

  public static void main(String[] args) {
        // 初始化长度为0
        ArrayList list = new ArrayList();//断点
  }      

En primer lugar más que empezar transferido al punto de interrupción, se iniciará la visualización predeterminada longitud ArrayList es cero;

En segundo lugar, introduzca el constructor

   public ArrayList() {
        // elementData 是 Object[] ---> 故 Arraylist底层由对象数组实现
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

Se puede observar que un DEFAULTCAPACITY_EMPTY_ELEMENTDATA asignado a elementData;

Echar un vistazo a lo que es DEFAULTCAPACITY_EMPTY_ELEMENTDATA, el código fuente a continuación, se puede ver una gran variedad de objetos última modificación [];

   // 共享的空数组实例,当第一个元素添加时从EMPTY_ELEMENTDATA辨别出扩张大小
   private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

elementData vistazo a lo que es el código fuente de la siguiente manera

    // 动态数组缓冲区,ArrayList存储元素的地方,elementData长度就是ArrayList长度
    // 当第一个元素添加时 DEFAULT_CAPACITY 被被扩张        
    transient Object[] elementData; // non-private to simplify nested class access

De nuevo en el depurador entrará en la clase padre para el diagrama de clases para ver Zhang ArrayList heredan la clase padre

entró cierto en el siguiente orden

AbstractList -> AbstractCollection -> Objeto

Curiosamente buscador de conocimiento durante el análisis también dio a conocer la siguiente línea de código se ejecuta, es decir, el número de lista para cambiar el tamaño del registro, si los cambios imprevistos ConcurrentModificationException arrojará una excepción, lo que explica por qué el iterador Lista no se puede utilizar para eliminar otras operaciones (aquí no extender iterador iterador, la fuente pertinente posteriormente análisis); esto es proporcionado por la forma de realización a prueba de rápido mecanismo;

Ciencia fail-fast mecanismo :

a prueba de rápido mecanismo de fallo es un mecanismo rápido, es decir, cuando se cambia la transmisión conjunto excepción estructura ConcurrentModificationException será lanzado, el error rápidamente para detectar un fallo para hacer la determinación;

// 记录list被修改的次数,也就是大小改变的次数
// 如果在迭代器中使用迭代,做出了不是期待的改变就会抛出ConcurrentModificationException
protected transient int modCount = 0;

Tip1: Lista A más adelante entrevista después de la llamada para eliminar el método de recogida en un proceso iterativo que pasa? R: He visto un buscador de la serie fuente de conocimiento ArrayList, se debe al fracaso rápido mecanismo detecta la ocurrencia de cambios estructurales Lista ConcurrentModificationException lanza una excepción; el momento no son de madera de altura, puedo responder que, debido a la colección tuvo lugar en el proceso de iteración eliminar, añadir, juego, al lado, las operaciones anteriores? Demasiado detalles de la misma, es demasiado bajo, la fuerza del entrevistador a subir de nivel, la cantidad de bien hacia atrás joven!

Consejo: aplicación matriz de objeto dinámico que subyace ArrayList

2.2 análisis inicial código fuente capacidad

ArrayList capacidad inicial generalmente para se crea un valor inicial dado matriz de objeto correspondiente al tamaño; no se da en el valor inicial, los miembros comparten atravesar array objeto vacío; excepción argumento de otra manera ilegal se tira de otro modo;

código de ensayo

public static void main(String[] args) {
        // 初始化为0
        ArrayList list = new ArrayList(5);
    }

fuente

    public ArrayList(int initialCapacity) {
        // 初始化容量大于0,创建指定大小的object数组
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        // 初始化容量等于0,空 object数组
        } else if (initialCapacity == 0) {
            // 其中 private static final Object[] EMPTY_ELEMENTDATA = {};
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            // 否则抛出非法参数异常
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

capacidad punta de un determinado tamaño rendimientos especificados para inicializar el tamaño especificado ArrayList ArrayList

2.3 Método de Análisis de fuente de complemento

código de ensayo

   public static void main(String[] args) {
        // 初始化为0
        ArrayList list = new ArrayList();
        list.add("a");
        System.out.println(list);
    }

En primer lugar: ver complemento fuente

  public boolean add(E e) {
        // 确保容量
        // size就是list的大小,也就是集包含合的元素个数
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

No se puede ver ensureCapacityInternal (tamaño + 1) un método para asegurar que la capacidad se puede derivar directamente de esta conclusión expresión añadiendo 1 a la longitud original de la matriz; mirada en el

    private void ensureCapacityInternal(int minCapacity) { 
    		// 期望大小 添加1个a 所以是1
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { 
        	// 判定是否是空数组
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); 
            // 在1 和 10(DEFAULT_CAPACITY)中取最大值
        }

        ensureExplicitCapacity(minCapacity);//此时就是10
    }

Puede concluir directamente que si, debido a la adición del elemento es 1, es deseable que la capacidad de 1, cuando después de la capacidad inicial en comparación con el valor máximo predeterminado, la depuración de la fuente 10 en ese punto, por lo que se desea después de la adición de un elemento ArrayList tamaño de expansión se expandió a 10

Buscamos para asegurar que la expansión del hormigón, además de una colección de cambio de número 1, si se desea una mayor expansión de mayor que la longitud de la ArrayList, será la expansión una vez más;

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;//list改变次数加1

        // overflow-conscious code
        //如果期望扩容小于元素ArrayList长度,会进行再次扩容
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);//扩容
    }

expansión Look grow(minCapacity);su aplicación interna es también muy simple idea, cada expansión son más el 50% en la Lista longitud original; si el tamaño de la matriz deseada supera la longitud máxima (valor máximo número entero int - 8) sobre el uso de longitud de agrupación como una int máximo valor entero y, por último, la matriz será copiada y tamaño de la matriz de re-designado; un lado retendrá el valor es las matrices de posición número 8 como marcadores de posición cabeza, si la longitud de la asignación supera la longitud máxima de la matriz MAX_ARRAY_SIZEse es arrojado OutOfMemoryError ,; la VM es generalmente esto limitará el tamaño de la práctica puede no ser la de MAX_ARRAY_SIZElanzar la mayor anomalía, por no mencionar el valor máximo de un entero;

    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;//oldCapacity=0 当前元素a未插入时的长度
        int newCapacity = oldCapacity + (oldCapacity >> 1);//newCapacity=0 原始长度 + 原始长度左移一位,也就是 除以2; 如果长度10,经过扩容后就是15
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;//(0-10)< 0 故 新的容量为10;即 newCapacity=10
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);///如果期望容量大于数组容量最大值就使用Int最大值;否则使用数组最大值
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);//数组拷贝,容量为10
    }

hugeCapacity (minCapacity); Fuente sigue

    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

Consejo: capacidad inicial ArrayList es 0, la expansión para añadir un elemento 10; después de más de 10 por longitud más expansión del 50% en la longitud original de la matriz; la longitud máxima de la ArrayList Integer.MAX_VALUE - 8; y finalmente llama Arrays. método CopyOf reasignado matriz de objetos

análisis de código fuente 2,4 conjunto

código de ensayo

    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add("a");
        list.set(0,"b");
        System.out.println(list);
    }

Primero en entrar en el método set

   public E set(int index, E element) {
        rangeCheck(index);// index =0 ; element = b ;检测ArrayList是否越界

        E oldValue = elementData(index);//获取原来数组索引对象
        elementData[index] = element;//根据对应重新赋值
        return oldValue;//返回对象
    }

La primera línea es para detectar si transfronteriza ArrayList

  private void rangeCheck(int index) {
        if (index >= size) // 给定索引大于等于数组长度抛出异常
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

La segunda línea se adquiere objeto posición original matriz de objetos;

  @SuppressWarnings("unchecked")
    E elementData(int index) {
        return (E) elementData[index];// index =0 ; elementData 是个 object[]
    }

La tercera línea reasignado de acuerdo con el índice, y vuelve; oldValue asi que aquí hay elementData [índice];

Consejo: ajusta el valor de la asignación es re ubicación de matriz; el equivalente de las operaciones de actualización, no hay una posición del elemento si se da, se producirá una excepción;

análisis de código fuente 2,5 get

código de ensayo

    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add("a");
        list.get(0);
        System.out.println(list);
    }

En el método get

  public E get(int index) {
        rangeCheck(index);//检测数组是否越界

        return elementData(index);//获取数组对应位置上的对象
    }

En consonancia con el conjunto posterior método o la llamada elementData obtener una matriz de objetos en una posición correspondiente; llegar nada método de punto extraño;

análisis de código fuente 2,6 remove

código de ensayo

    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add("a");
        list.add("b");
        list.remove(0);
        System.out.println(list);
    }

Fuente en su conjunto

    public E remove(int index) {
        rangeCheck(index);// 检测数组是否越界

        modCount++;//修改次数 +1
        E oldValue = elementData(index);//获取数组index位置上的值 oldValue=a

        int numMoved = size - index - 1;// numMoved = 2-0-1 = 1;表示移动的数量
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);//数组拷贝
        elementData[--size] = null; // clear to let GC do its work.数组长度 -1 位置置为null.

        return oldValue;//返回移除的值
    }

Aquí puede ser una breve descripción del método arraycopy

public static native void arraycopy(Object src,int  srcPos,Object dest, int destPos,int length);

parámetros

  • array src a copiar
  • srcPos iniciar la copia índice
  • dest matriz de destino
  • destPos comenzar a almacenar datos de localización
  • La longitud del número se coloca

Entonces no entienden la gente todavía deben confundirse, que dan un aspecto castañas

    public static void main(String[] args) {
        int[] src = new int[]{1,2,3,4,5};
        int[] desc = new int[]{6,7,8,9,10};
        System.arraycopy(src,2,desc,1,2);
        Arrays.stream(desc).boxed().forEach(des ->{
            System.out.println(des); // 6 ,3, 4, 9, 10
        });
    }

índice src = 2 comienza a partir del valor de la posición, se tarda unos pocos toma longitud = 2 (.e 3 y 4.); posición de inicio se coloca índice desc = 1, se completará en este momento está cubierta (3 , 4 anulaciones 7,8)

Entender los principios manta, a continuación, sólo dentro del código fuente es src y la descripción son en conjunto una matriz, suponiendo que desea borrar índice = 0 (es decir, los elementos 1); la copia de unos pocos? movNum = tamaño - índice -1 = 5 - 0- 1 = 4; Copia 4; 2,3,4,5 anula el src 1,2,3,4; finalmente obtenido 2, 4, 5 5; y, finalmente, el último elemento se establece en NULL para completar la operación de eliminación! ! Oh que se aprende, el buscador de conocimiento aprendido, el momento de altura todavía, después de escribir de estructuras de datos han hecho;

    public static void main(String[] args) {
        int[] src = new int[]{1,2,3,4,5};
        int[] desc = new int[]{1,2,3,4,5};
        System.arraycopy(src,1,desc,0,4);
        Arrays.stream(desc).boxed().forEach(des ->{
            System.out.println(des); // 2,3,4,5,5
        });

    }

Retire la boquilla se invoca el método System.arraycopy operativo subyacente, todos los elementos posteriores a los elementos de eliminación para quitar elementos copiados posición de índice, entonces el final de la matriz se establece en el nodo nulo

resume III

  1. Colección produce eliminar, añadir, juego, al lado de un proceso iterativo, las operaciones anteriores, se dispararán rápido quebrar mecanismo, no se espera hacer un cambio lanzará ConcurrentModificationException;
  2. Dinámica matriz de objeto ArrayList subyacente de ejecución, todas las ventajas y desventajas de ArrayList y matrices de buscar similar está conduciendo, adiciones y supresiones lentos;
  3. ArrayList capacidad inicial es 0, la expansión para añadir un elemento 10; después de más de 10 por longitud más el 50% de expansión en la longitud original de la matriz; longitud máxima ArrayList de Integer.MAX_VALUE - 8; la capacidad de un tamaño especificado dado para inicialización ArrayList ArrayList devuelve el tamaño determinado;
  4. reasignación es fijar el valor de posición de matriz; corresponde a la operación de actualización, y si no hay ningún elemento en una posición dada, arrojará una excepción;
  5. eliminar se invoca el método System.arraycopy operativo subyacente, todos los elementos posteriores de elementos de copia de eliminación para eliminar la ubicación de índice elemento, entonces el nodo se establece en el extremo de la nula array;

La mitad de un día pasado; buscadores de conocimiento tienen tiempo para solucionarlo arrayList de base distintos métodos;

Supongo que te gusta

Origin www.cnblogs.com/zszxz/p/12633169.html
Recomendado
Clasificación