LinkedList学习_迭代



LinkedList
  1. 底层数据结构是双向链表
  2. 实现了Deque接口,Deque接口继承了Queue接口,所以说LinkedList可以被当作队列来使用
  3. 成员变量
  1. size 链表的大小
  2. first 头节点
  3. last 尾节点
  1. 构造方法
  1. 空构造
  2. 集合构造
    public LinkedList(Collection<? extends E> c) { this(); addAll(c); }
  1. 核心操作方法
  1. add方法
  1. 逻辑:向链表的尾部追加元素
  2. 源码
    public boolean add(E e) { linkLast(e); return true; }
  3. linkLast方法
    void linkLast(E e) { // l = 尾节点 final Node<E> l = last; // 临时Node 元素 -> e 前节点 等于 旧的last final Node<E> newNode = new Node<>(l, e, null); // 尾节点 -> e last = newNode; // 尾节点为空 -> 链表就为空 // 因为如果是一个元素的话,first=last if (l == null) // 让头 -> e first = newNode; else // last <=> l l.next = newNode; size++; modCount++; }
  1. remove方法
  1. 逻辑:迭代 ,equals判断,存在就删除,指针(Node)位置调整
  2. 源码
    public boolean remove(Object o) { if (o == null) { // 判断链表里面的null元素,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; }
  3. unlink方法
    E unlink(Node<E> x) { // assert x != null; 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; } if (next == null) { last = prev; } else { next.prev = prev; x.next = null; } x.item = null; size--; modCount++; return element; }
  4. 图示
  1. get方法
  1. 逻辑
  1. 检查位置是否合法(​​本质就是index与size作比较​​)
  2. 返回元素
  1. 源码
    public E get(int index) { checkElementIndex(index); return node(index).item; }
  2. checkElementIndex(index)方法
    private void checkElementIndex(int index) { // 做一个异常抛出 if (!isElementIndex(index)) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }
  3. isElementIndex(index)方法
    private boolean isElementIndex(int index) { // index 范围在 0~size之间就是合法的 return index >= 0 && index < size; }
  4. node(index).item;
    Node<E> node(int index) { // 断言 下标不超出限制 // assert isElementIndex(index); // 为了速度和性能的提升 // 判断 index 离哪段比较近,那么就从那端开始遍历 if (index < (size >> 1)) { // index < 大小的一半 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; } }
  1. set方法
  1. 逻辑
  1. 检查边界
  2. 调用node()查找Node
  3. Node的​​item​​域赋值为新值
  4. 返回老值
  1. 源码
    public E set(int index, E element) { // 检查边界 checkElementIndex(index); // 调用node()查找Node Node<E> x = node(index); E oldVal = x.item; // Node的item域赋值为新值 x.item = element; // 返回老值 return oldVal; }