JDK之LinkedList源码解读(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_32523587/article/details/85941496

目录

构造函数

linkFirst(E e)

linkLast(E e)

linkBefore(E e, Node succ)


LinkedList由一系列Node节点组成,每一个节点指向前一个节点和后一个节点的引用,因此是一个双向链表。

构造函数

一个是无参的构造函数,一个参数是Collection c的构造函数。第二个构造函数调用addAll(c)方法。

size是LinkedList的元素个数。

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

        Object[] a = c.toArray();
        int numNew = a.length;
        if (numNew == 0)
            return false;

        Node<E> 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<E> newNode = new Node<>(pred, e, null);
            if (pred == null)
                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;
    }

先校验index的正确性 checkPositionIndex(index)

private void checkPositionIndex(int index) {
        if (!isPositionIndex(index))
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

private boolean isPositionIndex(int index) {
        return index >= 0 && index <= size;
    }

如果index小于0或者大于LinkedList的长度,则抛出越界异常。

linkFirst(E e)

 private void linkFirst(E e) {
        //将头结点赋值给临时变量f
        final Node<E> f = first;

        //创建一个新节点,它的前任节点为null,节点数据是传入的参数E e, 后续节点就是原来的头结点。这样一来,这个节点就变成了新的头结点
        final Node<E> newNode = new Node<>(null, e, f);

        //first再重新指向新的头结点
        first = newNode;

        //假如原先的头结点为null,说明原LinkedList是空的,那么last也指向这个新节点,因为这时候只有一个节点,所以该节点既是头结点,也是尾节点
        if (f == null)
            last = newNode;
        else        
            f.prev = newNode;
        //LinkedList长度加1
        size++;
        modCount++;
    }

作用:将新对象插入到LinkedList的头部,作为新的头结点。

linkLast(E e)

void linkLast(E e) {
        //将尾节点赋值给临时变量l
        final Node<E> l = last;

        //创建一个新节点,它的前任节点是原来的尾结点,节点数据是传入的参数E e, 后续节点为null。这样一来,这个节点就变成了新的头结点
        final Node<E> newNode = new Node<>(l, e, null);

        //last再重新指向新的尾结点
        last = newNode;

        //假如原先的尾结点为null,说明原LinkedList是空的,那么first也指向这个新节点,因为这时候只有一个节点,所以该节点既是头结点,也是尾节点
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        //LinkedList长度加1
        size++;
        modCount++;
    }

作用:将新对象插入到LinkedList的尾部,作为新的尾结点。

linkBefore(E e, Node<E> succ)

void linkBefore(E e, Node<E> succ) {
        // assert succ != null;
        final Node<E> pred = succ.prev;

        //创建一个新节点,它的前任节点是指定节点succ的前任节点,节点数据是传入的参数E e, 后续节点是该指定节点succ。这样一来,这个节点就插入到该节点succ的前面了
        final Node<E> newNode = new Node<>(pred, e, succ);

        //该节点succ前任节点变成了刚才插入的新节点了
        succ.prev = newNode;

        //假如原先的尾结点为null,说明原LinkedList是空的,那么first也指向这个新节点,因为这时候只有一个节点,所以该节点既是头结点,也是尾节点
        if (pred == null)
            first = newNode;
        else
            pred.next = newNode;
        //LinkedList长度加1
        size++;
        modCount++;
    }

作用:将新对象插入到LinkedList的指定节点前面。

猜你喜欢

转载自blog.csdn.net/qq_32523587/article/details/85941496