LinkedList源码

197 阅读2分钟

参考链接

根据参考链接的思路,分析源码可以以下几个方面进行:

  • 查看类图
  • 成员变量
  • 构造方法
  • 常用方法(增删改查)
  • 实现Deque接口部分
  • 遍历

1. 查看类图

Collection总的类图参考:链接

LinkedList的类图如下,其中实线为继承关系,虚线为接口实现关系。

LinkedList类图.awebp

  1. LinkedList 继承了 AbstrackSequentialList
  2. 实现了 List 接口以及 Deque 双向队列接口
  3. LinkedList 和 ArrayList 一样实现了序列化接口 Serializable 和 Cloneable 接口

2. 成员变量

image.png

// 节点个数
transient int size = 0;

// 链表的头节点
transient Node<E> first;

// 链表的尾节点
transient Node<E> last;

// 
private static final long serialVersionUID = 876323262645176354L;

3. 构造方法

image.png

// 空参构造
public LinkedList() {
}


// 使用一个集合来构造另一个集合,将原始集合的元素依次添加给新构造的集合

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

其中addAll方法为:

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

进一步调用下面的addAll方法:

/**
 * 在 index 节点前插入包含所有 c 集合元素的节点。
 * 返回值表示是否成功添加了对应的元素.
 */
public boolean addAll(int index, Collection<? extends E> c) {
   // 查看索引是否满足 0 =< index =< size 的要求
   checkPositionIndex(index);
    // 调用对应 Collection 实现类的 toArray 方法将集合转为数组
   Object[] a = c.toArray();
   //检查数组长度,如果为 0 则直接返回 false 表示没有添加任何元素
   int numNew = a.length;
   if (numNew == 0)
       return false;
   // 保存 index 当前的节点为 succ,当前节点的上一个节点为 pred
   Node<E> pred, succ;
   // 如果 index = size 表示在链表尾部插入
   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);
       //如果 pred 为空表示 LinkedList 集合中还没有元素
       //生成的第一个节点将作为头节点 赋值给 first 成员变量
       if (pred == null)
           first = newNode;
       else
           pred.next = newNode;
       pred = newNode;
   }
   // 如果 index 位置的元素为 null 则遍历数组后 pred 所指向的节点即为新链表的末节点,赋值给 last 成员变量
   if (succ == null) {
       last = pred;
   } else {
       // 否则将 pred 的 next 索引指向 succ ,succ 的 prev 索引指向 pred
       pred.next = succ;
       succ.prev = pred;
   }
   // 更新当前链表的长度 size 并返回 true 表示添加成功
   size += numNew;
   modCount++;
   return true;
}