4. Análisis del código fuente de LinkedList

1. Estructura de datos La
Inserte la descripción de la imagen aquí
estructura de datos subyacente de LinkedList es una lista doblemente enlazada. La estructura general se muestra en la figura anterior. Cada nodo en la lista enlazada se puede rastrear hacia adelante o hacia atrás.
Cada nodo de la lista enlazada se denomina Nodo. ​​El nodo tiene atributos prev y next, que representan las posiciones del nodo anterior y el siguiente, respectivamente.
el primero es el nodo principal de la lista doblemente enlazada, su nodo anterior es nulo, el último es el nodo de cola de la lista doblemente enlazada y su siguiente nodo también es nulo.
Cuando no hay datos en la lista vinculada, el primero y el último son el mismo nodo, y los puntos frontal y posterior son nulos.
Debido a que es una lista doblemente vinculada, siempre que la memoria de la máquina sea lo suficientemente potente, no hay límite de tamaño.
Código fuente

private static class Node<E> {
    
    
	//节点值
    E item;
    //当前节点的下一个节点
    Node<E> next; 
    //当前节点的前一个节点
    Node<E> prev; 
 
    //初始化参数顺序分别是前一个节点、本身节点和后一个节点
    Node(Node<E> prev, E element, Node<E> next) {
    
    
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}

Análisis de código fuente

  1. El nodo de nodo incluye tres atributos, a saber, el nodo anterior, su propio nodo y el siguiente nodo.
  2. La secuencia de parámetros de inicialización del nodo de nodo es el nodo anterior, su propio nodo y el siguiente nodo.

2. Agregar Al agregar un
nuevo nodo, puede optar por agregarlo al encabezado de la lista vinculada o agregarlo al final de la lista vinculada. El método de agregar por defecto se agrega desde el final, y el método addFirst es agregar desde el encabezado. El código fuente específico es el siguiente.
Código fuente

public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable{
    
    
	//从尾部开始追加节点
	void linkLast(E e) {
    
    
	    //尾节点赋值给临时变量
	    final Node<E> l = last;
	    //新建节点,l是新节点的前一个节点,e表示当前新节点,null表示当前新节点的后一个节点
	    final Node<E> newNode = new Node<>(l, e, null);
	    //将新节点追加到尾部
	    last = newNode;
	    //如果链表为空(l和尾节点相等,尾节点为空,链表即为空),头部和尾部是同一个节点且都是新建的节点
	    if (l == null)
	        first = newNode;
	    //否则把前一个节点的下一个节点指向当前节点
	    else
	        l.next = newNode;
	    //修改链表大小和版本
	    size++;
	    modCount++;
	}
	
	//从头部追加
	private void linkFirst(E e) {
    
    
	    //头节点赋值给临时变量
	    final Node<E> f = first;
	    //新建节点,null表示前一个节点,e表示当前新节点,f表示新节点的下一个节点,目前值是头节点的值
	    final Node<E> newNode = new Node<>(null, e, f);
	    //将新节点追加到头部
	    first = newNode;
	    //如果链表为空(f和头节点相等,头节点为空,链表即为空),头部和尾部是同一个节点且都是新建的节点
	    if (f == null)
	        last = newNode;
	    //否则把下一个节点的前一节点指向当前尾节点
	    else
	        f.prev = newNode;
	    //修改链表大小和版本
	    size++;
	    modCount++;
	}
}

Análisis
del código fuente A partir del código fuente, podemos ver que el método de agregar nodos en la cabeza y la cola es relativamente simple, simplemente modifique la posición de apuntado, pero el primero es el punto anterior del nodo de la cabeza móvil y el segundo es el siguiente punto del nodo de la cola móvil.

3. Consulta Es
relativamente lento consultar un determinado nodo en la lista enlazada, y necesita ser buscado uno por uno El código fuente específico es el siguiente.
Código fuente

public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable{
    
    
	//根据链表索引位置查询节点
	Node<E> node(int index) {
    
    
	    //如果index处于队列的前半部分,从头开始找,size >> 1是size除以2的意思
	    if (index < (size >> 1)) {
    
    
	        Node<E> x = first;
	        for (int i = 0; i < index; i++)
	            x = x.next;
	        return x;
	    } else {
    
    //如果index处于队列的后半部分,从尾部开始找
	        Node<E> x = last;
	        for (int i = size - 1; i > index; i--)
	            x = x.prev;
	        return x;
	    }
	}
}

Análisis del código fuente
Se puede encontrar en el código fuente que LinkedList no usa un bucle de principio a fin, sino una simple dicotomía Primero, vea si el índice está en la primera mitad o en la segunda mitad de la lista vinculada. Si es la primera mitad, empieza desde el principio y viceversa. De esta forma, el número de ciclos se reduce al menos a la mitad y se mejora la eficiencia de búsqueda, idea que vale la pena aprender.

4. La
interfaz Iterator no puede satisfacer las necesidades de LinkedList para lograr un acceso iterativo bidireccional (Iterator solo admite el acceso de principio a fin), por lo que Java ha agregado una interfaz iterativa ListIterator, que proporciona métodos de iteración hacia adelante y hacia atrás. Como hasPrevious, previous, previousIndex, hasNext, next y nextIndex. El código fuente de hasNext, next y remove son los siguientes.
Código fuente

public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable{
    
    
	//判断是否有下一个元素
	public boolean hasNext() {
    
    
		//下一个节点的索引小于链表的大小,就存在下一个元素
	    return nextIndex < size;
	}
	 
	//取下一个元素
	public E next() {
    
    
	    //检查期望版本号是否发生变化
	    checkForComodification();
	    //再次检查
	    if (!hasNext())
	        throw new NoSuchElementException();
	    //next是当前节点,在上一次执行next()方法时被赋值
	    lastReturned = next;
	    //next是下一个节点了,为下次迭代做准备
	    next = next.next;
	    nextIndex++;
	    return lastReturned.item;
	}
	
	public void remove() {
    
    
	    checkForComodification();
	    //lastReturned是本次迭代需要删除的值,分空和非空两种情况
	    //lastReturned为空,说明调用者没有主动执行过next()或者previos(),直接报错
	    //lastReturned不为空,是在上次执行next()或者previos()方法时赋的值
	    if (lastReturned == null)
	        throw new IllegalStateException();
	    Node<E> lastNext = lastReturned.next;
	    //删除当前节点
	    unlink(lastReturned);
	    /**
	     * next == lastReturned的场景分析
	     * 从尾到头递归执行,第一次迭代并且要删除最后一个元素的情况下,previous()方法里面设置了lastReturned = next = last,所以next和lastReturned会相等
	     */
	    if (next == lastReturned)
	        //这时候lastReturned是尾节点,lastNext是null,所以next也是null,这样在previous()执行时,发现next是null,就会把尾节点赋值给next
	        next = lastNext;
	    else
	        nextIndex--;
	    lastReturned = null;
	    expectedModCount++;
	}
}

5. Eliminación
El método para eliminar un nodo es similar a agregar. Puede elegir eliminar de la cabeza o de la cola. La operación de eliminación establecerá el valor del nodo y los nodos antes y después de él en nulo, y finalmente serán reciclados por el GC.
Código fuente

public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable{
    
    
	//头部删除 
	//f是链表头节点
	private E unlinkFirst(Node<E> f) {
    
    
	    //取出头节点的值作为方法的返回值
	    final E element = f.item;
	    //取出头节点的下一个节点
	    final Node<E> next = f.next;
	    //帮助GC回收头节点
	    f.item = null;
	    f.next = null;
	    //将头节点的下一个节点设置为头节点
	    first = next;
	    //如果next为空,表明链表为空
	    if (next == null)
	        last = null;
	    //链表不为空,将头节点的前一个节点指向null
	    else
	        next.prev = null;
	    //修改链表大小和版本
	    size--;
	    modCount++;
	    return element;
	}
}

Análisis de código fuente

  1. Se puede ver en el código fuente que la operación de eliminación de nodos de la estructura de la lista enlazada es relativamente simple, simplemente modifique los puntos de los nodos frontal y posterior. Por lo tanto, la velocidad de agregar y eliminar LinkedList es relativamente rápida.
  2. El código de nodo de eliminación final es similar al código de nodo de eliminación de encabezado.

Supongo que te gusta

Origin blog.csdn.net/Jgx1214/article/details/109064454
Recomendado
Clasificación