LinkedList源代码分析(基于JDK1.8)

1.首先看一下LinkedList的定义:
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable

由上述代码可以看出, LinkedList实现了 List, Deque, Cloneable, Serializable 接口, 说明 LinkedList是非同步可序列化的. Deque接口提供了双端队列的操作方法.

2. LinkedList类成员变量定义如下:
transient int size = 0;
transient Node<E> first;
transient Node<E> last;

由上述代码可见, LinkedList类成员用size记录容器大小, first指向链表第一个节点, last指向链表最后一个节点. Node类是LinkedList内部私有类:

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;
         }
}
3.LinkedList构造方法如下:
public LinkedList() {
}

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

由上述代码可见, LinkedList类一共有两种构造方法. 一个是无参构造函数, 另一个是接受Collection类型参数作为构造方法参数. 利用Collection进行构造方法中, 调用了addAll函数进行初始化. addAll方法定义如下:

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

而以Collection类型为参数的addAll方法又调用了addAll方法另外一个重载方法, size和c作为参数传递过去:

    public boolean addAll(int index, Collection<? extends E> c) {
        //对传递进来的index索引位置进行判断,判断index >= 0 && index <= size, 否则抛出IndexOutOfBoundsException异常
        checkPositionIndex(index);
        //将容器c中的元素转换成数组
        Object[] a = c.toArray();
        int numNew = a.length;
        if (numNew == 0)
            return false;
    //定义所插入节点的前驱和后继
        Node<E> pred, succ;
        if (index == size) {
        //如果传入的index等于LinkedList容量大小,说明在链表的末尾新加入节点.
            succ = null;
            pred = last;
        } else {
        //如果不是在链表末尾添加,则首先调用node()方法查找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)//说明新插入的节点称为头节点
                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;
    }
4.LinkedList类的getxxx方法:
public E getFirst() {
     final Node<E> f = first;
     if (f == null)
         throw new NoSuchElementException();
     return f.item;
}
    public E getLast() {
        final Node<E> l = last;
        if (l == null)
            throw new NoSuchElementException();
        return l.item;
    }

从上述代码可见, getFirst, getLast方法都是直接根据LinkedList类成员变量first, last得到相关结果. 当链表为空时, 将会抛出异常.

5.LinkedList类removexxxx方法:
    public E removeFirst() {
        final Node<E> f = first;
        if (f == null)
            throw new NoSuchElementException();
        return unlinkFirst(f);
    }

由上述代码可见, removeFirst方法实际是由unlinkFirst方法来完成. 当链表为空时, 方法将会抛出异常.

    private E unlinkFirst(Node<E> f) {
        final E element = f.item;
        final Node<E> next = f.next;
        f.item = null;
        f.next = null; // 用于帮助GC垃圾回收
        first = next;
        if (next == null)
            last = null;
        else
            next.prev = null;
        size--;
        modCount++;
        return element;
    }

removeLast方法同理.

6.addFirst方法和addLast方法:
    public void addFirst(E e) {
        linkFirst(e);
    }

    private void linkFirst(E e) {
        final Node<E> f = first;
        final Node<E> newNode = new Node<>(null, e, f);
        first = newNode;
        if (f == null)
            last = newNode;
        else
            f.prev = newNode;
        size++;
        modCount++;
    }

由上述代码可见, addFirst方法实际上是调用linkFirst方法来完成的. 通过将e构造生成新节点, 插入到链表的头部, 插入时判断链表头是否为空.
addLast方法同理.

7. contains方法:
    public boolean contains(Object o) {
        return indexOf(o) != -1;
    }

由上述代码可见, contains方法调用了indexof方法来实现, indexof方法定义如下:

    public int indexOf(Object o) {
        int index = 0;
        if (o == null) {
            for (Node<E> x = first; x != null; x = x.next) {
                if (x.item == null)
                    return index;
                index++;
            }
        } else {
            for (Node<E> x = first; x != null; x = x.next) {
                if (o.equals(x.item))
                    return index;
                index++;
            }
        }
        return -1;
    }

由上述代码可见, indexof方法从头节点开始进行逐个查找, 如果找到了, 则返回相应节点的index; 否则返回-1. contains方法便是根据indexof返回值是否为-1判断所查找值存在与否.

8.size方法:
    public int size() {
        return size;
    }
9. add方法:
    public boolean add(E e) {
        linkLast(e);
        return true;
    }

add方法与前面提到过的addLast方法是一样的.

10.remove方法:
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)) {  //equals方法判断是否相同
                    unlink(x);
                    return true;
                }
            }
        }
        return false;
    }
//remove调用unlink方法
    E unlink(Node<E> x) {
        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;  //帮助GC垃圾回收
        }

        if (next == null) {
            last = prev;
        } else {
            next.prev = prev;
            x.next = null;  //帮助GC垃圾回收
        }

        x.item = null;
        size--;
        modCount++;
        return element;
    }
11. clear方法:
    public void clear() {
        for (Node<E> x = first; x != null; ) {
            Node<E> next = x.next;
         //逐个设置为null, 帮助进行GC垃圾回收
            x.item = null;
            x.next = null;
            x.prev = null;
            x = next;
        }
        first = last = null;
        size = 0;
        modCount++;
    }
12.get(int index)方法:
    public E get(int index) {
        //边界检查index >= 0 && index < size;
        checkElementIndex(index);
        //调用node()函数返回index处的节点
        return node(index).item;
    }
13.set方法:
    public E set(int index, E element) {
        //先检查边界
        checkElementIndex(index);
        //查找并获取节点
        Node<E> x = node(index);
        E oldVal = x.item;
        x.item = element;
        //返回旧值
        return oldVal;
    }
14.add(int index, E element)方法:
    public void add(int index, E element) {
        //检查位置边界index >= 0 && index <= size;
        //与索引边界不同, 索引边界为index >= 0 && index < size;
        checkPositionIndex(index);

        if (index == size)
            linkLast(element);
        else
        //在索引处添加新节点,相当与在原来索引节点前添加新节点
            linkBefore(element, node(index));
    } 

linkLast方法前面已经分析过了, 下面来分析linkBefore方法:

    //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++;
    }
15. remove(int index)方法:
    public E remove(int index) {
        //检查元素节点边界
        checkElementIndex(index);
        //前面已经分析过unlink方法
        return unlink(node(index));
    }
16.lastIndexof方法:
public int lastIndexOf(Object o) {
        int index = size;
        if (o == null) {
            //从链表尾部往回遍历
            for (Node<E> x = last; x != null; x = x.prev) {
                index--;
                if (x.item == null)
                    return index;
            }
        } else {
            for (Node<E> x = last; x != null; x = x.prev) {
                index--;
                if (o.equals(x.item))
                    return index;
            }
        }
        return -1;
    }
17.peek和element方法:
    public E peek() {
        final Node<E> f = first;
        return (f == null) ? null : f.item;
    }

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

由上述代码可见, peek方法和element方法目的都是为了读取链表的第一个元素. 但是, peek方法在链表为空时返回值为null; 而element方法调用getFirst方法, 当链表为空时, getFirst方法将会抛出异常.

18. poll和remove方法:
    public E poll() {
        final Node<E> f = first;
        return (f == null) ? null : unlinkFirst(f);
    }

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

如上述代码所见, poll和remove都是删除链表头部元素并返回删除的头部元素值. 不同点在于, 当链表为空时, poll方法将会返回null; 而remove方法将会直接抛出异常.

19.offer和offerFirst方法:
    //将元素添加到链表末尾
    public boolean offer(E e) {
        return add(e);
    }
    //将元素添加到链表头部
    public boolean offerFirst(E e) {
        addFirst(e);
        return true;
    }
    //将元素添加到链表尾部
    public boolean offerLast(E e) {
        addLast(e);
        return true;
    }
20.peekFirst和peekLast方法:
    //返回链表头部元素
    public E peekFirst() {
        final Node<E> f = first;
        return (f == null) ? null : f.item;
     }
    //返回链表尾部元素
    public E peekLast() {
        final Node<E> l = last;
        return (l == null) ? null : l.item;
    }
21.pollFirst和pollLast方法:
    //删除头部元素
    public E pollFirst() {
        final Node<E> f = first;
        return (f == null) ? null : unlinkFirst(f);
    }
    //删除尾部元素
    public E pollLast() {
        final Node<E> l = last;
        return (l == null) ? null : unlinkLast(l);
    }

由上述代码可见, 当链表为空时, 将会返回null值.

22.push方法:
    public void push(E e) {
        addFirst(e);
    }
23.pop方法:
    //当链表为空时, 将会抛出异常
    public E pop() {
        return removeFirst();
    }
24.removeFirstOccurrence方法:
    //实际上调用remove方法来完成.
    //当给定元素存在时返回true, 否则返回false
    public boolean removeFirstOccurrence(Object o) {
        return remove(o);
    }
25.removeLastOccurrence方法:
//删除给定元素最后出现的那一个,如果给定元素存在则返回true;否则返回false.
    public boolean removeLastOccurrence(Object o) {
        if (o == null) {
            //从后往前遍历
            for (Node<E> x = last; x != null; x = x.prev) {
                if (x.item == null) {
                    unlink(x);
                    return true;
                }
            }
        } else {
            for (Node<E> x = last; x != null; x = x.prev) {
                if (o.equals(x.item)) {
                    unlink(x);
                    return true;
                }
            }
        }
        return false;
    }
26. listIterator方法:
    public ListIterator<E> listIterator(int index) {
        //检查位置索引
        checkPositionIndex(index);
        //返回ListItr类
        return new ListItr(index);
    }

ListItr类是LinkedList内部私有类:

private class ListItr implements ListIterator<E> {
        private Node<E> lastReturned;
        private Node<E> next;   //保存当前索引所对应的节点
        private int nextIndex;
        private int expectedModCount = modCount;
        ListItr(int index) {
            // 判断索引的位置
            next = (index == size) ? null : node(index);
            nextIndex = index;
        }

        public boolean hasNext() {
        //当索引小于链表的长度时,说明依然存在
            return nextIndex < size;
        }

        public E next() {
        //判断并发数据是否被修改
            checkForComodification();
            //如果不存在下一个元素,则会抛出NoSuchElementException异常
            if (!hasNext())
                throw new NoSuchElementException();

            lastReturned = next;
            next = next.next;
            nextIndex++;
            return lastReturned.item;
        }
        //用于判断并发操作下的数据修改, 从而提供快速失败机制. 
        //当数据被其他线程修改时, 将会抛出ConcurrentModificationException异常
        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

在上述代码中, 只是选取了ListItr类其中常用的hasNext, next方法进行分析.

27.descendingIterator方法:
public Iterator<E> descendingIterator() {
        //返回内部私有类DescendingIterator类
        return new DescendingIterator();
    }
private class DescendingIterator implements Iterator<E> {
        //调用前面分析过的私有内部类ListItr
        private final ListItr itr = new ListItr(size());
        public boolean hasNext() {
            return itr.hasPrevious();
        }
        public E next() {
            return itr.previous();
        }
        public void remove() {
            itr.remove();
        }
 }

 私有内部类ListItr的previous, hasPrevious方法如下:
 public boolean hasPrevious() {
             //条件是nextIndex>0
            return nextIndex > 0;
        }

 public E previous() {
      checkForComodification();
      if (!hasPrevious())
          throw new NoSuchElementException();
        //这是为了协调调用next方法, 因为当调用next方法后, 再调用previous方法
      lastReturned = next = (next == null) ? last : next.prev;
      nextIndex--;
      return lastReturned.item;
  }
28.clone方法:
public Object clone() {
        //调用superClone方法, 返回LinkedList对象
        LinkedList<E> clone = superClone();
        clone.first = clone.last = null;
        clone.size = 0;
        clone.modCount = 0;
        //将链表中的所有节点添加到新链表中
        for (Node<E> x = first; x != null; x = x.next)
            clone.add(x.item);

        return clone;
    }
    private LinkedList<E> superClone() {
        try {
            //调用Object.clone方法, 进行强制转换
            return (LinkedList<E>) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e);
        }
    }
29.toArray方法:
    //返回Object[]数组
    public Object[] toArray() {
        Object[] result = new Object[size];
        int i = 0;
        for (Node<E> x = first; x != null; x = x.next)
            result[i++] = x.item;
        return result;
    }
    //返回T[]数组
    public <T> T[] toArray(T[] a) {
    //当传入数组大小不足时, 需要进行扩展
        if (a.length < size)
            a = (T[])java.lang.reflect.Array.newInstance(
                                a.getClass().getComponentType(), size);
        int i = 0;
        Object[] result = a;
        for (Node<E> x = first; x != null; x = x.next)
            result[i++] = x.item;
        //如果数组的大小大于链表长度, 将数组size索引位置处设置为null
        if (a.length > size)
            a[size] = null;

        return a;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值