这些方法的实现都很简单。注意后一个方法 add(int index, E element) ,这个方法是在指定的位置插入元素。首先判断位置是否越界,然后判断是不是后一个位置。如果是直接插入链表末尾,否则调用 linkBefore(element, node(index) 方法。这里在传参数的时候又调用了 node(index) ,这个方法的目的是找到这个位置的节点对象,代码如下:
  Node<E> node(int index) {
  // assert isElementIndex(index);
  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;
  }
  }
  这里有个小技巧是先判断位置是在链表的前半段还是后半段,然后决定从链表的头还是尾去寻找节点。要注意的是 遍历链表寻找节点的时间复杂度是 O(n) ,即使做了位置的判断,坏情况下也要遍历链表中一半的元素。所以此时插入操作的时间复杂度不是 O(1) ,而是 O(n/2)+O(1) 。用于查找指定位置元素的 get(int index) 方法便是调用 node 实现的:
  public E get(int index) {
  checkElementIndex(index);
  return node(index).item;
  }
  再看一下 remove 方法:
  public E remove(int index) {
  checkElementIndex(index);
  return unlink(node(index));
  }
  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)) {
  unlink(x);
  return true;
  }
  }
  }
  return false;
  }
  第一个 remove(int index) 方法同样要调用 node(index) 寻找节点。而第二个方法 remove(Object o) 是删除指定元素,这个方法要依次遍历节点进行元素的比较,坏情况下要比较到后一个元素,比调用 node 方法更慢,时间复杂度为 O(n) 。另外从这个方法可以看出 LinkedList 的元素可以是 null 。
  总结
  LinkedList 基于双向链表实现,元素可以为 null 。
  LinkedList 插入、删除元素比较快,如果只要调整指针的指向那么时间复杂度是 O(1) ,但是如果针对特定位置需要遍历时,时间复杂度是 O(n) 。