Java集合源码分析—LinkedList

Posted <天各一方>

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java集合源码分析—LinkedList相关的知识,希望对你有一定的参考价值。

LinkedList源码分析

LinkedList结构

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable

LinkedList继承自AbstractSequentialList<E>,实现了List、Deque、Cloneable、Serializable接口。

LinkedList内部是一个双向链表结构。

源码分析

属性

// 元素个数
transient int size = 0;

// 指向第一个节点
transient Node<E> first;

// 指向最后一个节点
transient Node<E> last;

// 内部类,用于实现链表
private static class Node<E> 
    E item; // 存储的元素
    Node<E> next; // 下一个节点 尾元素的next指向null
    Node<E> prev; // 上一个节点 头元素的prev指向null

    Node(Node<E> prev, E element, Node<E> next) 
        this.item = element;
        this.next = next;
        this.prev = prev;
    

构造

// 默认构造方法,size为0,first和last为空
public LinkedList() 

public LinkedList(Collection<? extends E> c) 
    this();
    addAll(c);

public boolean addAll(Collection<? extends E> c) 
    return addAll(size, c);

public boolean addAll(int index, Collection<? extends E> c) 
    checkPositionIndex(index);

    // 将集合转化为数组
    Object[] a = c.toArray();
    int numNew = a.length;
    // 数组长度为0,直接返回false
    if (numNew == 0)
        return false;
	// pred表示前驱节点,succ是当前要插入的位置
    Node<E> pred, succ;
    if (index == size) 
        // 添加到list的末尾
        succ = null;
        pred = last;
     else 
        // 添加到指定位置,即index前
        succ = node(index);
        pred = succ.prev;
    

    // 遍历数组,将其连成链表
    for (Object o : a) 
        @SuppressWarnings("unchecked") E e = (E) o;
        Node<E> newNode = new Node<>(pred, e, null);
        if (pred == null)
            // 如果list表为空,新节点为首节点
            first = newNode;
        else
            // 如果存在前节点,前节点会向后指向新加的节点
            pred.next = newNode;
        //新加的节点成为前一个节点
        pred = newNode;
    
	//添加集合中的元素完成后,将指定位置后面的元素连到链表后方
    if (succ == null) 
        last = pred;
     else 
        pred.next = succ;
        succ.prev = pred;
    

    size += numNew;
    modCount++;
    return true;

方法

add(E e)

// 将元素插入链表末尾
public boolean add(E e) 
    linkLast(e);
    return true;

void linkLast(E e) 
    final Node<E> l = last;
    final Node<E> newNode = new Node<>(l, e, null);
    // 更新last节点为新节点
    last = newNode;
    if (l == null)
        // 如果last节点为null,将新节点设为first
        first = newNode;
    else
        // 否则,将last节点的next指向新节点
        l.next = newNode;
    size++;
    modCount++;

add(int index,E element)

public void add(int index, E element) 
    checkPositionIndex(index);

    if (index == size)
        linkLast(element);
    else
        linkBefore(element, node(index));

Node<E> node(int index) 
    
    if (index < (size >> 1)) 
        Node<E> x = first;
        for (int i = 0; i < index; i++)
            x = x.next;
        return x;
     else 
        Node<E> x = last;
        for (int i = size - 1; i > index; i--)
            x = x.prev;
        return x;
    

// 在指定节点前插入节点,节点succ不能为空
void linkBefore(E e, Node<E> succ) 
    //取出指定节点的前驱节点
    final Node<E> pred = succ.prev;
    final Node<E> newNode = new Node<>(pred, e, succ);
    //修改指定节点的前驱为新节点
    succ.prev = newNode;
    if (pred == null)
        first = newNode;
    else
        pred.next = newNode;
    size++;
    modCount++;

remove()

public E remove() 
    return removeFirst();

public E removeFirst() 
    final Node<E> f = first;
    if (f == null)
        throw new NoSuchElementException();
    return unlinkFirst(f);

private E unlinkFirst(Node<E> f) 
    // assert f == first && f != null;
    final E element = f.item;// 取出首节点元素
    final Node<E> next = f.next;// 得到下一个节点
    f.item = null;// 将首节点元素置空
    f.next = null;// 将节点后继置空,帮助回收
    first = next;// 首节点的下一个节点成为新的首节点
    if (next == null)
        last = null;
    else
        next.prev = null;
    size--;
    modCount++;
    return element;

remove(Object o)

public boolean remove(Object o) 
    if (o == null) 
        for (Node<E> x = first; x != null; x = x.next) 
            if (x.item == null) 
                unlink(x);
                return true;
            
        
     else 
        for (Node<E> x = first; x != null; x = x.next) 
            if (o.equals(x.item)) 
                unlink(x);
                return true;
            
        
    
    return false;

E unlink(Node<E> x) 
    // assert x != null;
    final E element = x.item;//取出节点的元素
    final Node<E> next = x.next;//取出节点的下一个节点
    final Node<E> prev = x.prev;//取出节点的上一个节点

    if (prev == null) 
        //如果前一个节点为空(如当前节点为首节点),后一个节点成为新的首节点
        first = next;
     else 
        //如果前一个节点不为空,那么他的后继指向当前的下一个节点
        prev.next = next;
        x.prev = null;
    

    if (next == null) 
        //如果后一个节点为空(如当前节点为尾节点),当前节点前一个成为新的尾节点
        last = prev;
     else 
        //如果后一个节点不为空,后一个节点向前指向当前的前一个节点
        next.prev = prev;
        x.next = null;
    

    x.item = null;
    size--;
    modCount++;
    return element;

remove(int index)

public E remove(int index) 
    checkElementIndex(index);
    return unlink(node(index));

以上是关于Java集合源码分析—LinkedList的主要内容,如果未能解决你的问题,请参考以下文章

Java集合源码分析—LinkedList

Java集合源码分析—LinkedList

Java集合源码分析—LinkedList

Java集合源码分析LinkedList

java集合系列之LinkedList源码分析

Java集合源码分析之LinkedList