LinkedList源码分析

LinkedList源码分析

继承实现

public class LinkedList<E> 
extends AbstractSequentialList<E> 
implements List<E>, Deque<E>, Queue<E>, Cloneable, Serializable
  • LinkedList 是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列列或双端队列进行操作。
  • LinkedList 实现 List 接⼝口,能对它进行队列操作。
  • LinkedList 实现 Deque 接⼝口,双向队列,它支持从两个端点方向检索和插入元素。
  • LinkedList 实现了 Cloneable 接口,即覆盖了函数clone(),能克隆。
  • LinkedList 实现 java.io.Serializable 接口,这意味着LinkedList支持序列化,能通过序列化去传输。

重要属性

// 链表的大小
transient int size = 0;
// 头结点
transient Link<E> voidLink;

transient:不会参与序列化

内部类

    private static final class Link<ET> {
        ET data; // 数据域
        Link<ET> previous, next; // 前驱和后继
        Link(ET o, Link<ET> p, Link<ET> n) {
            data = o;
            previous = p;
            next = n;
        }
    }
  • LinkedList存储的数据是以链表形式存储的,每一个节点对应的类就是Link

  • 很明显,每一个Link节点包含一个数据域和两个指针域

LinkIterator

  • LinkedList对应的迭代器,用于遍历
重要属性
int pos, expectedModCount; // 位置和扩展的计数器
final LinkedList<ET> list; // 迭代器自己的LinkedList
Link<ET> link, lastLink; // 当前节点和最后节点
构造方法
        LinkIterator(LinkedList<ET> object, int location) {
            list = object; // 保存传入的LinkedList
            expectedModCount = list.modCount; // 保存传入的LinkedList的计数器
            if (location >= 0 && location <= list.size) { // 确保location不越界
                if (location < list.size / 2) {
                    /*
                        如果location = 0
                            不会执行下面的循环
                        如果location >= 1
                            执行下面循环,但现在link = null,会报NullPointerException【已验证】

                        如果listIterator方法传入0,location = 0,不会报异常。但不会执行下面循环。
                        如果传入>0,会报NullPointerException

                    */
                    for (pos = -1; pos + 1 < location; pos++) {
                        link = link.next;
                    }
                } else {
                    /*
                        如果location = 0 && list.size == [0, 1]
                            会执行下面的循环
                        如果location > 0 && location >= list.size/2 && location <= list.size
                            也会执行下面的循环

                        但总的来说,因为link属性为null。所以无论.next还是.previous都会报异常。

                    */
                    for (pos = list.size; pos >= location; pos--) {
                        link = link.previous;
                    }
                }

                /*
                    总结:绝大多数时候,调用listIterator()方法默认是不会传参数的,但其内部默认传的是0.
                    因此基本上走的是 if (location < list.size / 2)判断,而正是因为location = 0,所以里面的for循环是不会走的。
                    相当于,这个if循环就是个摆设!

                    这个构造方法的存在的意义也就是将传来的object集合存储,赋值给list属性!
                */
            } else {
                throw new IndexOutOfBoundsException();
            }
        }
        // 添加一个节点
        // 添加新节点是添加在link位置之后的
        public void add(ET object) {
            if (expectedModCount == list.modCount) {
                Link<ET> next = link.next;
                // 新节点在link和link.next之间
                Link<ET> newLink = new Link<ET>(object, link, next);
                // link和newLink进行双向链接
                link.next = newLink;
                next.previous = newLink;
                // 让新节点成当前节点
                link = newLink;
                lastLink = null;
                pos++; // link位置++
                expectedModCount++;
                list.size++;
                list.modCount++;
            } else {
                throw new ConcurrentModificationException();
            }
        }

        // 是否有下一个节点(不包括头节点)
        public boolean hasNext() {
            // 这是双向链表,所以如果当前节点的下一个节点不是头结点
            // 就说明还有下一个节点
            return link.next != list.voidLink;
        }

        // 是否有上一个节点(不包括头节点)
        public boolean hasPrevious() {
            // 头结点也是一个节点,所以当前节点不是头结点的话
            // 最起码前面还有一个头结点存在
            return link != list.voidLink;
        }

        // 获取下一个节点的数据
        public ET next() {
            if (expectedModCount == list.modCount) {
                LinkedList.Link<ET> next = link.next; // 首先获取当前节点的下一个节点
                if (next != list.voidLink) { // 然后判断这个"下一个节点"是不是有效的
                    lastLink = link = next; // 确定"下一个节点"有效,赋值lastLink和link
                    pos++; // 移位
                    return link.data; // 返回"下一个节点"的数据
                }
                throw new NoSuchElementException();
            }
            throw new ConcurrentModificationException();
        }

        public int nextIndex() {
            return pos + 1;
        }

        // 获取上一个节点的数据
        public ET previous() {
            if (expectedModCount == list.modCount) {
                // 判断是否还有前一个节点,判断标准是当前节点而非当前节点的前一个节点
                // 因为对于上一个节点来说,头节点也可以是上一个节点
                if (link != list.voidLink) { 
                    lastLink = link; // 将当前节点设置为最后节点
                    link = link.previous; // 将上一个节点设置为当前节点
                    pos--;
                    return lastLink.data; // 返回当前节点的数据
                }
                throw new NoSuchElementException();
            }
            throw new ConcurrentModificationException();
        }

        public int previousIndex() {
            return pos;
        }

        // 删除一个节点
        public void remove() {
            if (expectedModCount == list.modCount) {
                // 删除的是lastLink
                if (lastLink != null) {
                    // 取出lastLink的 前一个/后一个 节点
                    Link<ET> next = lastLink.next;
                    Link<ET> previous = lastLink.previous;
                    // 并将前一节点和后一节点衔接起来,相当于lastLink已经不需要了
                    next.previous = previous; 
                    previous.next = next;
                    if (lastLink == link) {
                        pos--;
                    }
                    // 将前一节点设为当前节点,lastLink置为null
                    link = previous;
                    lastLink = null;
                    expectedModCount++;
                    list.size--;
                    list.modCount++;
                } else {
                    throw new IllegalStateException();
                }
            } else {
                throw new ConcurrentModificationException();
            }
        }

        // 设置值给lastLink.data
        public void set(ET object) {
            if (expectedModCount == list.modCount) {
                if (lastLink != null) {
                    lastLink.data = object;
                } else {
                    throw new IllegalStateException();
                }
            } else {
                throw new ConcurrentModificationException();
            }
        }
  • 关于这个LinkIterator感到很奇怪,因为没看到让linklastLink不为null的地方。无论是构造方法还是功能功能方法,上来都是直接使用。但经我测试会报NullPointerException
功能方法
        // 添加一个节点
        // 添加新节点是添加在link位置之后的
        public void add(ET object) {
            if (expectedModCount == list.modCount) {
                Link<ET> next = link.next;
                // 新节点在link和link.next之间
                Link<ET> newLink = new Link<ET>(object, link, next);
                // link和newLink进行双向链接
                link.next = newLink;
                next.previous = newLink;
                // 让新节点成当前节点
                link = newLink;
                lastLink = null;
                pos++; // link位置++
                expectedModCount++;
                list.size++;
                list.modCount++;
            } else {
                throw new ConcurrentModificationException();
            }
        }

        // 是否有下一个节点(不包括头节点)
        public boolean hasNext() {
            // 这是双向链表,所以如果当前节点的下一个节点不是头结点
            // 就说明还有下一个节点
            return link.next != list.voidLink;
        }

        // 是否有上一个节点(不包括头节点)
        public boolean hasPrevious() {
            // 头结点也是一个节点,所以当前节点不是头结点的话
            // 最起码前面还有一个头结点存在
            return link != list.voidLink;
        }

        // 获取下一个节点的数据
        public ET next() {
            if (expectedModCount == list.modCount) {
                LinkedList.Link<ET> next = link.next; // 首先获取当前节点的下一个节点
                if (next != list.voidLink) { // 然后判断这个"下一个节点"是不是有效的
                    lastLink = link = next; // 确定"下一个节点"有效,赋值lastLink和link
                    pos++; // 移位
                    return link.data; // 返回"下一个节点"的数据
                }
                throw new NoSuchElementException();
            }
            throw new ConcurrentModificationException();
        }

        public int nextIndex() {
            return pos + 1;
        }

        // 获取上一个节点的数据
        public ET previous() {
            if (expectedModCount == list.modCount) {
                // 判断是否还有前一个节点,判断标准是当前节点而非当前节点的前一个节点
                // 因为对于上一个节点来说,头节点也可以是上一个节点
                if (link != list.voidLink) { 
                    lastLink = link; // 将当前节点设置为最后节点
                    link = link.previous; // 将上一个节点设置为当前节点
                    pos--;
                    return lastLink.data; // 返回当前节点的数据
                }
                throw new NoSuchElementException();
            }
            throw new ConcurrentModificationException();
        }

        public int previousIndex() {
            return pos;
        }

        // 删除一个节点
        public void remove() {
            if (expectedModCount == list.modCount) {
                // 删除的是lastLink
                if (lastLink != null) {
                    // 取出lastLink的 前一个/后一个 节点
                    Link<ET> next = lastLink.next;
                    Link<ET> previous = lastLink.previous;
                    // 并将前一节点和后一节点衔接起来,相当于lastLink已经不需要了
                    next.previous = previous; 
                    previous.next = next;
                    if (lastLink == link) {
                        pos--;
                    }
                    // 将前一节点设为当前节点,lastLink置为null
                    link = previous;
                    lastLink = null;
                    expectedModCount++;
                    list.size--;
                    list.modCount++;
                } else {
                    throw new IllegalStateException();
                }
            } else {
                throw new ConcurrentModificationException();
            }
        }

        // 设置值给lastLink.data
        public void set(ET object) {
            if (expectedModCount == list.modCount) {
                if (lastLink != null) {
                    lastLink.data = object;
                } else {
                    throw new IllegalStateException();
                }
            } else {
                throw new ConcurrentModificationException();
            }
        }

ReverseLinkIterator

重要属性
// 存储LinkedList的属性
private final LinkedList<ET> list;
// 节点
private Link<ET> link;
// 是否可以删除
private boolean canRemove;
构造方法
        ReverseLinkIterator(LinkedList<ET> linkedList) {
            list = linkedList; // 存储集合
            expectedModCount = list.modCount;
            link = list.voidLink; // 存储头节点
            canRemove = false;
        }
功能方法
        // 是否有上一个节点
        public boolean hasNext() {
            // 因为是reverse,所以是previous
            return link.previous != list.voidLink;
        }

        public ET next() {
            if (expectedModCount == list.modCount) {
                if (hasNext()) {
                    link = link.previous; // 获取到上一个节点
                    canRemove = true;
                    return link.data; // 返回上一个节点的数据
                }
                throw new NoSuchElementException();
            }
            throw new ConcurrentModificationException();

        }

        // 移除掉当前节点——link节点
        public void remove() {
            if (expectedModCount == list.modCount) {
                if (canRemove) { // 如果可以删除,调用next时canRemove为true
                    // 获取到link的前后节点
                    Link<ET> next = link.previous;
                    Link<ET> previous = link.next;
                    // 让link的前后节点进行链接,然后删除link节点(gc)
                    next.next = previous;
                    previous.previous = next;
                    // 让link的后一个节点作为当前节点
                    link = previous;
                    list.size--;
                    list.modCount++;
                    expectedModCount++;
                    canRemove = false;
                    return;
                }
                throw new IllegalStateException();
            }
            throw new ConcurrentModificationException();
        }

功能方法

add

     // 指定位置添加节点
    @Override
    public void add(int location, E object) {
        if (location >= 0 && location <= size) { // 确定location在有效范围之内
            Link<E> link = voidLink; // 取得头节点
            if (location < (size / 2)) { // 如果是在链表的前半段
                for (int i = 0; i <= location; i++) {
                    link = link.next; // 不断循环,直到link指向location位置的link
                }
            } else { // 如果是在链表的后半段
                for (int i = size; i > location; i--) {
                    link = link.previous; // 不断循环,直到link指向location位置的link
                }
            }

            // 到这里,link已经是location位置上的link了

            // 新建newLink,位置在location-1和location之间
            Link<E> previous = link.previous;
            Link<E> newLink = new Link<E>(object, previous, link);

            // 让location-1链接到newLink
            // 让location链接到newLink
            previous.next = newLink;
            link.previous = newLink;
            // 至此,newLink正式插入到location位置节点之前!
            size++;
            modCount++;
        } else {
            throw new IndexOutOfBoundsException();
        }
    }

addLast

    @Override
    public boolean add(E object) {
        return addLastImpl(object);
    }

    private boolean addLastImpl(E object) {
        // 新建newLink在voidLink.previous和voidLink之间,并让newLink连接前后节点
        Link<E> oldLast = voidLink.previous;
        Link<E> newLink = new Link<E>(object, oldLast, voidLink);
        // 让前后节点连接newLink
        voidLink.previous = newLink;
        oldLast.next = newLink;
        size++;
        modCount++;
        return true;
    }

addAll

     // 将一个集合插入到链表中指定位置
    @Override
    public boolean addAll(int location, Collection<? extends E> collection) {
        if (location < 0 || location > size) { // 确定添加位置的有效性
            throw new IndexOutOfBoundsException();
        }
        int adding = collection.size(); // 要添加的集合元素个数
        if (adding == 0) {
            return false;
        }
        // 看看要添加的集合是否是LinkedList
        Collection<? extends E> elements = (collection == this) ?
                new ArrayList<E>(collection) : collection;

        Link<E> previous = voidLink;
        // 判断location在链表的前/后半段,因为LinkedList是双向链表,因此
        // .next和.previous永远都是有效的。voidLink是头节点,由它开始.next或.previous
        // 都没问题。最终previous会指向location位置的节点。
        if (location < (size / 2)) {
            for (int i = 0; i < location; i++) {
                previous = previous.next;
            }
        } else {
            for (int i = size; i >= location; i--) {
                previous = previous.previous;
            }
        }
        Link<E> next = previous.next;
        for (E e : elements) {
            // 不断循环从location节点.next开始,链接collection中的链表
            Link<E> newLink = new Link<E>(e, previous, null);
            previous.next = newLink;
            previous = newLink;
        }
        // 将collection中的链表最后一个节点.next链接到"原location.next节点"
        previous.next = next;
        // 双向绑定
        next.previous = previous;
        // 最终连接完毕!
        size += adding;
        modCount++;
        return true;
    }
     // 添加一个集合,位置:双向链表末尾(头部)
    @Override
    public boolean addAll(Collection<? extends E> collection) {
        int adding = collection.size(); // 要添加的集合元素个数
        if (adding == 0) {
            return false;
        }
        // 看看要添加的集合是否是ArrayList
        Collection<? extends E> elements = (collection == this) ?
                new ArrayList<E>(collection) : collection;

        Link<E> previous = voidLink.previous;
        // 添加collection到LinkedList,添加位置从头节点.previous开始。
        // 所以可以说将collection添加到链表尾部,也可以说添加到头部
        // 毕竟这一个一个双向循环链表
        for (E e : elements) {
            Link<E> newLink = new Link<E>(e, previous, null);
            previous.next = newLink;
            previous = newLink;
        }
        // 双向绑定
        previous.next = voidLink;
        voidLink.previous = previous;
        size += adding;
        modCount++;
        return true;
    }

addFirst

    public void addFirst(E object) {
        addFirstImpl(object);
    }

    // 添加元素在头节点之后
    private boolean addFirstImpl(E object) {
        // 新建的节点在voidLink和voidLink.next之间
        Link<E> oldFirst = voidLink.next;
        Link<E> newLink = new Link<E>(object, voidLink, oldFirst);
        // 双向绑定
        voidLink.next = newLink;
        oldFirst.previous = newLink;
        size++;
        modCount++;
        return true;
    }

clear

    @Override
    public void clear() {
        if (size > 0) {
            size = 0;
            // 最关键的两句!
            // 头节点.next 断掉 指向自己
            // 头节点.previous 断掉 指向自己
            // 中间一大段链表没人指向,会自动gc
            voidLink.next = voidLink;
            voidLink.previous = voidLink;
            modCount++;
        }
    }

contains

    @Override
    public boolean contains(Object object) {
        Link<E> link = voidLink.next;
        if (object != null) {
            while (link != voidLink) { // 如果==,说明压根没元素,只有头节点自己而已
                if (object.equals(link.data)) { // 节点比较的是数据域
                    return true;
                }
                link = link.next; // 不断指向下一个节点
            }
        } else {
            while (link != voidLink) { // 如果==,说明压根没元素,只有头节点自己而已
                if (link.data == null) { // 节点比较的是数据域
                    return true; 
                } 
                link = link.next; // 不断指向下一个节点
            }
        }
        return false;
    }

get

    @Override
    public E get(int location) {
        if (location >= 0 && location < size) { // 确定location在有效范围之内
            Link<E> link = voidLink;
            if (location < (size / 2)) { // 查找分前半段和后半段,可以提高效率
                for (int i = 0; i <= location; i++) {
                    link = link.next;
                }
            } else {
                for (int i = size; i > location; i--) {
                    link = link.previous;
                }
            }
            // 最终找到location位置上的节点,返回其数据域
            return link.data;
        }
        throw new IndexOutOfBoundsException();
    }

getFirst

    public E getFirst() {
        return getFirstImpl();
    }

    // 获取第一个节点的数据
    private E getFirstImpl() {
        Link<E> first = voidLink.next;
        if (first != voidLink) { // 头节点算第0个节点,要获取的是头节点.next(第1个节点)
            return first.data; // 返回第1个节点的数据
        }
        throw new NoSuchElementException();
    }

getLast

    // 获取最后一个节点的数据
    public E getLast() {
        // 第0个节点的上一个节点就是最后一个节点
        Link<E> last = voidLink.previous;
        if (last != voidLink) { // 不是头节点就行
            return last.data;
        }
        throw new NoSuchElementException();
    }

indexOf

    // 从前往后进行数据域的比较
    @Override
    public int indexOf(Object object) {
        int pos = 0;
        Link<E> link = voidLink.next;
        if (object != null) {
            while (link != voidLink) { // 从第1个节点开始遍历进行比较
                if (object.equals(link.data)) {
                    return pos;
                }
                link = link.next;
                pos++;
            }
        } else {
            while (link != voidLink) { // 数据域是null也可以,所以也在比较之列
                if (link.data == null) {
                    return pos;
                }
                link = link.next;
                pos++;
            }
        }
        return -1;
    }

lastIndexOf

     // 从后往前进行数据域的比较
    @Override
    public int lastIndexOf(Object object) {
        int pos = size;
        Link<E> link = voidLink.previous;
        if (object != null) {
            // indexOf从第1个节点开始往后比较,那么lastIndexOf就从最后一个节点开始
            // 往前比较,而比较方式一样
            while (link != voidLink) {
                pos--;
                if (object.equals(link.data)) {
                    return pos;
                }
                link = link.previous;
            }
        } else {
            while (link != voidLink) {
                pos--;
                if (link.data == null) {
                    return pos;
                }
                link = link.previous;
            }
        }
        return -1;
    }

remove

    @Override
    public E remove(int location) {
        if (location >= 0 && location < size) { // 确定location在有效范围之内
            Link<E> link = voidLink;
            if (location < (size / 2)) { // 分前半段和后半段查找,提高效率
                for (int i = 0; i <= location; i++) {
                    link = link.next;
                }
            } else {
                for (int i = size; i > location; i--) {
                    link = link.previous;
                }
            }
            // 遍历完,link指向location位置的节点
            // 让link的前后节点进行链接,然后删除link节点
            Link<E> previous = link.previous;
            Link<E> next = link.next;
            previous.next = next;
            next.previous = previous;
            size--;
            modCount++;
            return link.data;
        }
        throw new IndexOutOfBoundsException();
    }

removeFirst

    public E removeFirst() {
        return removeFirstImpl();
    }

    private E removeFirstImpl() {
        Link<E> first = voidLink.next; // 先获取第1个节点
        if (first != voidLink) { // 如果第1个节点不是头节点
            // 让第1个节点的前后节点链接,然后删除第1个节点
            Link<E> next = first.next;
            voidLink.next = next;
            next.previous = voidLink;
            size--;
            modCount++;
            return first.data;
        }
        throw new NoSuchElementException();
    }

removeLast

    public E removeLast() {
        return removeLastImpl();
    }

    private E removeLastImpl() {
        Link<E> last = voidLink.previous; // 获取最后一个节点
        if (last != voidLink) { // 如果最后一个节点不是头节点
            // 让最后一个节点的前后节点相连,然后不再指向最后节点,自动被gc
            Link<E> previous = last.previous;
            voidLink.previous = previous;
            previous.next = voidLink;
            size--;
            modCount++;
            return last.data;
        }
        throw new NoSuchElementException();
    }

peekLast

    // 返回最后一个节点的数据
    public E peekLast() {
        Link<E> last = voidLink.previous;
        return (last == voidLink) ? null : last.data;
    }

pollFirst

    // 返回第一个节点的数据并移除第一个节点
    public E pollFirst() {
        return (size == 0) ? null : removeFirstImpl();
    }

pollLast

    // 返回最后一个节点的数据并移除最后一个节点
    public E pollLast() {
        return (size == 0) ? null : removeLastImpl();
    }

pop

    // 返回第一个节点的数据并移除第一个节点
    public E pop() {
        return removeFirstImpl();
    }

push

    // 添加元素到链表的第一个位置
    public void push(E e) {
        addFirstImpl(e);
    }

set

    @Override
    public E set(int location, E object) {
        if (location >= 0 && location < size) { // 确定location在有效范围之内
            Link<E> link = voidLink; // 获取头节点
            if (location < (size / 2)) { // 分段查询
                for (int i = 0; i <= location; i++) {
                    link = link.next;
                }
            } else {
                for (int i = size; i > location; i--) {
                    link = link.previous;
                }
            }
            // 遍历完毕,link此时指向location位置的节点
            // 赋值数据域
            E result = link.data;
            link.data = object;
            return result;
        }
        throw new IndexOutOfBoundsException();
    }

poll

    // 返回第一个节点的数据并移除第一个节点
    public E poll() {
        return size == 0 ? null : removeFirst();
    }

remove

    // 移除第1个节点并返回
    public E remove() {
        return removeFirstImpl();
    }

offer

    // 添加元素到链表的最后一个位置
    public boolean offer(E o) {
        return addLastImpl(o);
    }

peek

    // 返回第1个节点的数据
    public E peek() {
        return peekFirstImpl();
    }

    private E peekFirstImpl() {
        Link<E> first = voidLink.next;
        return first == voidLink ? null : first.data;
    }

toArray

    @Override
    public Object[] toArray() {
        int index = 0;
        Object[] contents = new Object[size]; // 新建集合大小的数组
        Link<E> link = voidLink.next; // 获取到第一个节点
        while (link != voidLink) {
            contents[index++] = link.data; // 不断循环将链表每个节点的数据赋值给数组
            link = link.next;
        }
        return contents;
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值