LinkedList

一、概述

LinkedList底层数据结构是基于双向链表实现的,实现了List,和ArrayList一样元素顺序和插入顺序保持一致,不过由于是链表实现,本身是无容量限制的,所以没有初始容量设置也没有扩容需求。

public class LinkedList
    extends AbstractSequentialList
    implements List, Deque, Cloneable, java.io.Serializable
{
    transient int size = 0;

    /**
     * Pointer to first node.
     * Invariant: (first == null && last == null) ||
     *            (first.prev == null && first.item != null)
     */
    transient Node first;

    /**
     * Pointer to last node.
     * Invariant: (first == null && last == null) ||
     *            (last.next == null && last.item != null)
     */
    transient Node last;

Node节点如下:

private static class Node {
        E item;
        Node next;
        Node prev;

        Node(Node prev, E element, Node next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }

由上可以看到,每个节点包含了前后指针实现双向链表,同时LinkedList保留了first、last头指针和尾指针。为何size、first、last都要transient修饰我暂时还没悟透,等后续补上。LinkedList不擅长随机访问,对于set(i)、get(i)需要从头遍历(如果i大于size的一半则从尾遍历)

二、主要实现

1、构造函数

1)、LinkedList():构造空list;
2)、LinkedList(Collection c):构造一个包含c中元素的LinkedList,可以看出构建的链表是双向的

/**
     * Constructs an empty list.
     */
    public LinkedList() {
    }

    /**
     * Constructs a list containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     *
     * @param  c the collection whose elements are to be placed into this list
     * @throws NullPointerException if the specified collection is null
     */
    public LinkedList(Collection c) {
        this();
        addAll(c);
    }
public boolean addAll(Collection c) {
        return addAll(size, c);
    }

public boolean addAll(int index, Collection c) {
        checkPositionIndex(index);

        Object[] a = c.toArray();
        int numNew = a.length;
        if (numNew == 0)
            return false;
        //succ是插入位置的节点,pred是前一个节点
        Node pred, succ;
        if (index == size) {
            succ = null;
            pred = last;
        } else {
            succ = node(index);
            pred = succ.prev;
        }

        for (Object o : a) {
            @SuppressWarnings("unchecked") E e = (E) o;
            Node newNode = new Node<>(pred, e, null);//构造一新节点,设置pred,next在下次循环中设置
            //此处主要是前一个对象的next
            if (pred == null)
                first = newNode;
            else
                pred.next = newNode;//代表上一个节点的next
            pred = newNode;
        }

        if (succ == null) {
            last = pred;
        } else {
            pred.next = succ;
            succ.prev = pred;
        }

        size += numNew;
        modCount++;
        return true;
    }
    /**
     * Returns the (non-null) Node at the specified element index.
     */
    Node node(int index) {
        // assert isElementIndex(index);
       //遍历链表的方向,小于一半的从first往后遍历,否则从last往前遍历
        if (index < (size >> 1)) {
            Node x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {
            Node x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }
2、新增

新增的相关方法有多个,由于篇幅有限,就只分析add(int index, E element)

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

        if (index == size)
            //这个比较简单,就是在链表尾部新增一个元素
            linkLast(element);
        else
            //在index处插入element
            linkBefore(element, node(index));
    }
    /**
     * Links e as last element.
     */
    void linkLast(E e) {
        final Node l = last;
        final Node newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    }  
    /**
     * Inserts element e before non-null Node succ.
     */
    void linkBefore(E e, Node succ) {
        // assert succ != null;
        final Node pred = succ.prev;
        final Node newNode = new Node<>(pred, e, succ);
        succ.prev = newNode;
        if (pred == null)
            first = newNode;
        else
            pred.next = newNode;
        size++;
        modCount++;
    }

add(int index, E element):在此列表中指定的位置插入指定的元素。
addAll(Collection c):添加指定 collection 中的所有元素到此列表的结尾,顺序是指定 collection 的迭代器返回这些元素的顺序。
addAll(int index, Collection c):将指定 collection 中的所有元素从指定位置开始插入此列表。
AddFirst(E e): 将指定元素插入此列表的开头。
addLast(E e): 将指定元素添加到此列表的结尾。

2、删除

同样,由于篇幅有限,仅介绍下remove(int index),关键代码是unlink(),代码逻辑很清晰,并无难懂之处

    public E remove(int index) {
        checkElementIndex(index);
        return unlink(node(index));
    }
    /**
     * Unlinks non-null node x.
     */
    E unlink(Node x) {
        // assert x != null;
        final E element = x.item;
        final Node next = x.next;
        final Node 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;
    }

clear(): 从此列表中移除所有元素。
remove():获取并移除此列表的头(第一个元素)。
remove(int index):移除此列表中指定位置处的元素。
remove(Objec o):从此列表中移除首次出现的指定元素(如果存在)。
removeFirst():移除并返回此列表的第一个元素。
removeFirstOccurrence(Object o):从此列表中移除第一次出现的指定元素(从头部到尾部遍历列表时)。
removeLast():移除并返回此列表的最后一个元素。
removeLastOccurrence(Object o):从此列表中移除最后一次出现的指定元素(从头部到尾部遍历列表时)。

你可能感兴趣的:(LinkedList)