JDK8 LinkedList源码解读

LinkedList源码分析

1.链表介绍

链表是一种物理存储单元上非连续、非顺序的存储结构,数组元素的逻辑顺序是通过链表中的指针连接次序实现的。链表由一系列节点(链表中每一个元素都称为节点)组成,节点可以在运行时动态生成。每一个节点都包括两部分:一个是存储数据元素的数据域、另一个是存储下一个节点地址的指针域。

双向链表是链表的一种,由节点组成,每一个数据节点中都有两个指针,分别指向直接后继和直接前驱。

2.LinkedList的底层实现

LinkedList是基于双向链表实现的;

源码


1.构造方法

/**
   * 空参构造方法
   */
public LinkedList() {
    
    
}
/**
   * 带参构造方法
   *
   * @param c
   */
public LinkedList(Collection<? extends E> c) {
    
    
  this();
  addAll(c);
}

/**
   * 将集合中的所有元素追加到此列表未部
   * @param c
   * @return
   */
public boolean addAll(Collection<? extends E> c) {
    
    
  return addAll(size, c);
}

插入方法

  • add(E e)方法
/**
	* 在链表的尾部添加一个新的节点
  */
public boolean add(E e) {
    
    
  linkLast(e);
  return true;
}

/**
	* 链表中e作为最后一个元素
  *
  * Links e as last element.
  */
void linkLast(E e) {
    
    
  //前继节点
  final Node<E> l = last;
  //新节点
  // newNode = (l,e,null) ==> newNode = (前继节点,新创建的节,未部节点)
  final Node<E> newNode = new Node<>(l, e, null);
  //将原来的前继节替换成当前的新节点(设置新节点为尾节点)
  last = newNode;
  //判断指向最后一个节点的指针是否null
  //如果为null,说明链表中没有元素节点;那么现在这个链表的头节点和为节点是新创建的节点
  if (l == null)
    first = newNode;
  //如果不为null;设置原继节点的后继节点为新创建的节点
  else
    l.next = newNode;
  //集合的长度加一
  size++;
  //链表被修改的次数加一
  modCount++;
}
  • add(int index, E element)方法
/**
	* 向指定位置新增一个新的节点
	*/
public void add(int index, E element) {
    
    
  //检查index是否合法
  checkPositionIndex(index);
  //判断index是不是尾部节点,如果是直接插入到该位置(链表的尾部)
  if (index == size)
    linkLast(element);
  else
    //element 要插入的元素
    //node(index) 原先的元素的节点
    linkBefore(element, node(index));
}

/**
	* 向链表的尾部插入一个元素
	*/
void linkLast(E e) {
    
    
  //前继节点
  final Node<E> l = last;
  //新节点
  // newNode = (l,e,null) ==> newNode = (前继节点,新创建的节,未部节点)
  final Node<E> newNode = new Node<>(l, e, null);
  //将原来的前继节替换成当前的新节点(设置新节点为尾节点)
  last = newNode;
  //判断指向最后一个节点的指针是否null
  //如果为null,说明链表中没有元素节点;那么现在这个链表的头节点和为节点是新创建的节点
  if (l == null)
    first = newNode;
  //如果不为null;设置原继节点的后继节点为新创建的节点
  else
    l.next = newNode;
  //集合的长度加一
  size++;
  //链表被修改的次数加一
  modCount++;
}
/**
	* 在链表的指定位置之间插入一个元素
	*/
void linkBefore(E e, Node<E> succ) {
    
    
  // assert succ != null;
  //获取当前索引位置节点的前继节点(原先元素的前继节点)
  final Node<E> pred = succ.prev;
  // newNode = pred <-- e --> succ
  /**
     * 这段代码什么意思,比方说:我现在的linked集合中有这些元素{1,2,3}
     * 我现在向index=1的位置插入一个元素8,得到的结果是{1,8,2,3};
     * 那么它做的事情就是先获取index=1元素的前继节点
     * 接着就是创建新的节点,这个新的节点的位置就是:index索引的前继节点、新的节点、index索引所在的节点
     * pred <-- e --> succ
     */
  final Node<E> newNode = new Node<>(pred, e, succ);
  //原先元素的前继节点就是当前插入元素的节点(修改原节点的前继节点为新创建的节点)
  succ.prev = newNode;
  //如果原先元素的前继节点为null,很显然它是在链表的头部插入元素了,那么开始节点就等于这个新创建的节点
  if (pred == null)
    first = newNode;
  //不等于null,原先元素的前继节点的后继节点就等于新创建的节点
  else
    pred.next = newNode;
  //链表的长度加 +1
  size++;
  //链表被修改的次数 +1
  modCount++;
}
  • addFirst(E e)
/**
   * 将指定的元素插入到此列表的开头。
   * Inserts the specified element at the beginning of this list.
   *
   * @param e the element to add 要添加的元素
   */
public void addFirst(E e) {
    
    
  linkFirst(e);
}

/**
	 * 链接e作为第一个元素。
   * Links e as first element.
   */
  private void linkFirst(E e) {
    
    
    //头节点
    final Node<E> f = first;
    //新节点,新节点的直接前驱为null(因为它是新的头节点),直接后继为原头节点
    final Node<E> newNode = new Node<>(null, e, f);
    //头节点等于新节点
    first = newNode;
    //如果头节点为null,那么当前这个链表中是没有节点的,添加的节点就是链表中的第一个节点
    //那么尾节点也是新创建的节点
    if (f == null)
      last = newNode;
    else
      //头节点不为null,原头节点的直接前驱指针指向新的节点(当前的头节点)
      f.prev = newNode;
    //链表的长度 +1
    size++;
    //链表被修改的次数+1
    modCount++;
  }
  • addLast(E e)方法
/**
   * 将指定的元素追加到此列表的末尾。
   * Appends the specified element to the end of this list.
   *
   * <p>This method is equivalent to {@link #add}. 这个方法相当于add(E e)
   *
   * @param e the element to add 要添加的元素
   */
public void addLast(E e) {
    
    
  linkLast(e);
}
/**
	* 链表中e作为最后一个元素
  *
  * Links e as last element.
  */
void linkLast(E e) {
    
    
  //前继节点
  final Node<E> l = last;
  //新节点
  // newNode = (l,e,null) ==> newNode = (前继节点,新创建的节,未部节点)
  final Node<E> newNode = new Node<>(l, e, null);
  //将原来的前继节替换成当前的新节点(设置新节点为尾节点)
  last = newNode;
  //判断指向最后一个节点的指针是否null
  //如果为null,说明链表中没有元素节点;那么现在这个链表的头节点和为节点是新创建的节点
  if (l == null)
    first = newNode;
  //如果不为null;设置原继节点的后继节点为新创建的节点
  else
    l.next = newNode;
  //集合的长度加一
  size++;
  //链表被修改的次数加一
  modCount++;
}

删除方法

  • remove()方法
/**
	* 该方法的目的就是断开头节点,让头节点的后继节点取代头节点
	*/
public E remove() {
    
    
  return removeFirst();
}

public E removeFirst() {
    
    
  //获取头节点
  final Node<E> f = first;
  //判断头节点是否为空
  //如果为空抛出`没有这样的元素异常`程序终止运行
  //不为空则调用unlinkFirst(f)方法移除头节点
  if (f == null)
    throw new NoSuchElementException();
  return unlinkFirst(f);
}

private E unlinkFirst(Node<E> f) {
    
    
  // assert f == first && f != null;
  //获取头节点的元素
  final E element = f.item;
  //获取头节点的后继节点
  final Node<E> next = f.next;
  //将头节点的元素值至为空
  f.item = null;
  //将头节点的后继节点至为空
  f.next = null; // help GC
  //新的头节点就等于原头节点的后继节点
  first = next;
  //如果头节点的后继节点为null,说明这个链表中只有这么一个数据。那么头节点后尾节点都为null
  if (next == null)
    last = null;
  //头节点的后继节点不为null,则原头节点至为null
  else
    next.prev = null;
  //链表长度 -1
  size--;
  //链表被修改的次数 + 1
  modCount++;
  //返回被移除的元素值
  return element;
}
  • remove(Object o)方法
/**
	* 断开指定元素所在的节点
	*/
public boolean remove(Object o) {
    
    
  //判断方法传入的值是否为null
  //如果为null遍历链表找到为元素null的节点,调用 unlink(x) 方法断开节点并将该节点的元素值至为null
  //方法传入的值不为null,和为null的操作一致
  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)) {
    
    
        unlink(x);
        return true;
      }
    }
  }
  return false;
}

/**
   * 断开非空节点x的链接
   * Unlinks non-null node x.
   */
E unlink(Node<E> x) {
    
    
  // assert x != null;
  //获取该x节点的元素值
  final E element = x.item;
  //获取x节点的后继节点
  final Node<E> next = x.next;
  //获取x节点的前继节点
  final Node<E> prev = x.prev;

  //判断x节点的前继节点是否为null,如果为null,则说明需要断开的节点就是头节点
  //那么,新的头节点就是x节点的后节点
  if (prev == null) {
    
    
    first = next;
    //x节点的前继节点不为null,就将x节点的前继节点指针指向x节点的后继节点,然后再断开x节点
  } else {
    
    
    prev.next = next;
    x.prev = null;
  }
  //如果x节点的后继节点为null,则说明要断开的节点就是尾节点
  //那么新的尾节点就是x节点的前至节点
  if (next == null) {
    
    
    last = prev;
    //x节点的后继节点不为null,则将x节点的后继节点的指针指向x节点的前继节点,然后断开x节点,此时已经完成移除操作
  } else {
    
    
    next.prev = prev;
    x.next = null;
  }
  //将x节点的元素值至为null
  x.item = null;
  //链表的长度 -1
  size--;
  //链表被修改的次数 + 1
  modCount++;
  //将移除的元素值返回
  return element;
}
  • remove(int index)方法
/**
	* 断开指定位置下的节点
  */
public E remove(int index) {
    
    
  //检查index是否合法
  checkElementIndex(index);
  //node(index) 获取index位置元素
  return unlink(node(index));
}

/**
	* 返回指定元素索引处的(非空)节点。
	*/
Node<E> node(int index) {
    
    
  // assert isElementIndex(index);

  //判断index 小于元素size/2
  //从前往后找
  if (index < (size >> 1)) {
    
    
    //获取头节点
    Node<E> x = first;
    //循环取到index位置的节点
    for (int i = 0; i < index; i++)
      x = x.next;
    return x;
    //从后往前找  
  } else {
    
    
    //获取尾节点
    Node<E> x = last;
    //循环取到index位置的节点
    for (int i = size - 1; i > index; i--)
      x = x.prev;
    return x;
  }
}

/**
	* 断开非空节点x的链接。
	* Unlinks non-null node x.
  */
E unlink(Node<E> x) {
    
    
  // assert x != null;
  //获取x节点下的元素值
  final E element = x.item;
  //获取x节点的后继节点
  final Node<E> next = x.next;
  //获取x节点的前继节点
  final Node<E> prev = x.prev;

  //判断x节点的前继节点是否为null,如果为null说明要断开的节点就是头节点
  //那么新的头节点就是原头节点(x)的后继节点
  if (prev == null) {
    
    
    first = next;
    //x节点的前继节点不为null,则将x节点的前继节点的指针指向x节点的后继指针
    //并断开x节点的前继节点指向x节点的指针
  } else {
    
    
    prev.next = next;
    x.prev = null;
  }

  //判断x节点的后继节点是否为null,如果为null说明要断开的节点就是尾节点
  //那么新的尾节点就是原尾节点(x)的前继节点
  if (next == null) {
    
    
    last = prev;
  } else {
    
    
    //x节点的后继节点不等于null,则将x节点的后继节点指针指向x节点的前继节点
    //断开x节点的后继节点指向x节点的指针,x节点的直接前驱指针和直接后继指针都已经断开了即x节点已经断开
    next.prev = prev;
    x.next = null;
  }
  //将x节点的元素值置为null
  x.item = null;
  //链表的长度 -1
  size--;
  //链表被修改的次数 +1
  modCount++;
  //将移除的元素返回
  return element;
}

查找方法

  • get(int index)
/**
   * 返回列表中指定位置的元素
   * Returns the element at the specified position in this list.
   *
   * @param index index of the element to return 要返回的元素的索引
   * @return the element at the specified position in this list 元素位于此列表中的指定位置
   * @throws IndexOutOfBoundsException {@inheritDoc}
   */
public E get(int index) {
    
    
  //检查index是否合法(检查索引是否越界,如果越界抛出`索引越界异常`)
  checkElementIndex(index);
  // 返回该节点的元素值
  return node(index).item;
}

/**
   * 返回指定元素索引处的(非空)节点。
   * Returns the (non-null) Node at the specified element index.
   */
Node<E> node(int index) {
    
    
  // assert isElementIndex(index);
  //判断index 是否小于(size/2)
  //如果小于从前往后找
  if (index < (size >> 1)) {
    
    
    Node<E> x = first;
    //遍历获取节点,并将节点返回
    for (int i = 0; i < index; i++)
      x = x.next;
    return x;
    //大于,从后往前找
  } else {
    
    
    Node<E> x = last;
    //遍历获取节点,并将节点返回
    for (int i = size - 1; i > index; i--)
      x = x.prev;
    return x;
  }
}

遍历(Iterator)

   /**
     * Returns an iterator over the elements in this list (in proper
     * sequence). 在列表中的元素上返回一个迭代器(以适当的顺序)
     *
     * This implementation merely returns a list iterator over the list.
     * 此实现仅返回列表迭代器
     *
     * @return an iterator over the elements in this list (in proper sequence) 对列表中的元素返回一个迭代器(以适当的顺序)
     */
public Iterator<E> iterator() {
    
    
  return listIterator();
}

public ListIterator<E> listIterator() {
    
    
  return listIterator(0);
}

public ListIterator<E> listIterator(final int index) {
    
    
  rangeCheckForAdd(index);

  return new ListItr(index);
}

private class ListItr extends Itr implements ListIterator<E> {
    
    
  ListItr(int index) {
    
    
    cursor = index;
  }

  public boolean hasPrevious() {
    
    
    return cursor != 0;
  }

  public E previous() {
    
    
    checkForComodification();
    try {
    
    
      int i = cursor - 1;
      E previous = get(i);
      lastRet = cursor = i;
      return previous;
    } catch (IndexOutOfBoundsException e) {
    
    
      checkForComodification();
      throw new NoSuchElementException();
    }
  }

  public int nextIndex() {
    
    
    return cursor;
  }

  public int previousIndex() {
    
    
    return cursor-1;
  }

  public void set(E e) {
    
    
    if (lastRet < 0)
      throw new IllegalStateException();
    checkForComodification();

    try {
    
    
      AbstractList.this.set(lastRet, e);
      expectedModCount = modCount;
    } catch (IndexOutOfBoundsException ex) {
    
    
      throw new ConcurrentModificationException();
    }
  }

  public void add(E e) {
    
    
    checkForComodification();

    try {
    
    
      int i = cursor;
      AbstractList.this.add(i, e);
      lastRet = -1;
      cursor = i + 1;
      expectedModCount = modCount;
    } catch (IndexOutOfBoundsException ex) {
    
    
      throw new ConcurrentModificationException();
    }
  }
}

private class Itr implements Iterator<E> {
    
    
  /**
  	* 元素的索引,由后续对next的调用返回。
    */
  int cursor = 0;

  /**
  	* 最近一次调用next或previous返回的元素的索引。如果通过调用remove删除此元素,则重置为-1。
    */
  int lastRet = -1;

  /**
  	* 迭代器认为支持列表应该具有的mod计数值。如果违背了这个期望,迭代器就会检测到并发修改。
    */
  int expectedModCount = modCount;

  
  /**
  	* 判断是否下一个迭代元素
  	*/
  public boolean hasNext() {
    
    
    return cursor != size();
  }

  /**
  	* 获取元素的值
  	*/
  public E next() {
    
    
    checkForComodification();
    try {
    
    
      int i = cursor;
      E next = get(i);
      lastRet = i;
      cursor = i + 1;
      return next;
    } catch (IndexOutOfBoundsException e) {
    
    
      checkForComodification();
      throw new NoSuchElementException();
    }
  }

  public void remove() {
    
    
    if (lastRet < 0)
      throw new IllegalStateException();
    checkForComodification();

    try {
    
    
      AbstractList.this.remove(lastRet);
      if (lastRet < cursor)
        cursor--;
      lastRet = -1;
      expectedModCount = modCount;
    } catch (IndexOutOfBoundsException e) {
    
    
      throw new ConcurrentModificationException();
    }
  }

  final void checkForComodification() {
    
    
    if (modCount != expectedModCount)
      throw new ConcurrentModificationException();
  }
}

public interface Iterator<E> {
    
    
  /**
     * Returns {@code true} if the iteration has more elements.
     * (In other words, returns {@code true} if {@link #next} would
     * return an element rather than throwing an exception.)
     *
     * @return {@code true} if the iteration has more elements
     */
  boolean hasNext();

  /**
     * Returns the next element in the iteration.
     *
     * @return the next element in the iteration
     * @throws NoSuchElementException if the iteration has no more elements
     */
  E next();

  /**
     * Removes from the underlying collection the last element returned
     * by this iterator (optional operation).  This method can be called
     * only once per call to {@link #next}.  The behavior of an iterator
     * is unspecified if the underlying collection is modified while the
     * iteration is in progress in any way other than by calling this
     * method.
     *
     * @implSpec
     * The default implementation throws an instance of
     * {@link UnsupportedOperationException} and performs no other action.
     *
     * @throws UnsupportedOperationException if the {@code remove}
     *         operation is not supported by this iterator
     *
     * @throws IllegalStateException if the {@code next} method has not
     *         yet been called, or the {@code remove} method has already
     *         been called after the last call to the {@code next}
     *         method
     */
  default void remove() {
    
    
    throw new UnsupportedOperationException("remove");
  }

  /**
     * Performs the given action for each remaining element until all elements
     * have been processed or the action throws an exception.  Actions are
     * performed in the order of iteration, if that order is specified.
     * Exceptions thrown by the action are relayed to the caller.
     */
  default void forEachRemaining(Consumer<? super E> action) {
    
    
    Objects.requireNonNull(action);
    while (hasNext())
      action.accept(next());
  }

猜你喜欢

转载自blog.csdn.net/ScholarTang/article/details/106507373