1.先看下内部的增删改查方法,对外的方法都是建立在内部方法基础上的
a.插入到头结点之前
/** * Links e as first element. */ private void linkFirst(E e) { final Node<E> f = first; final Node<E> newNode = new Node<>(null, e, f);//新建节点,prev为null,next为原有头结点 first = newNode;//头结点改成新插入的节点 if (f == null)//如果头结点为null,说明是第一次插入 last = newNode; else f.prev = newNode; size++; modCount++; }
b.加入尾节点之后
/** * Links e as last element. */ void linkLast(E e) { final Node<E> l = last; final Node<E> newNode = new Node<>(l, e, null); last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; modCount++; }
c.插入指定节点之前
/** * Inserts element e before non-null Node succ. */ void linkBefore(E e, Node<E> succ) { // assert succ != null; final Node<E> pred = succ.prev;//取到succ的前一个节点 final Node<E> newNode = new Node<>(pred, e, succ);//新建节点,prev是succ的prev,next是succ succ.prev = newNode;//改变succ的prev if (pred == null) first = newNode; else pred.next = newNode;//改变succ的prev的next size++; modCount++; }
d.删除头节点
/** * Unlinks non-null first node f. */ private E unlinkFirst(Node<E> f) { // assert f == first && f != null; final E element = f.item;//节点的内容 final Node<E> next = f.next;//节点next f.item = null; f.next = null; // help GC first = next;//头结点设成f的next if (next == null)//如果只有一个节点 last = null; else next.prev = null;f的next变成头结点,则f的next的prev设成null size--; modCount++; return element; }
e.删除尾节点
/** * Unlinks non-null last node l. */ private E unlinkLast(Node<E> l) { // assert l == last && l != null; final E element = l.item; final Node<E> prev = l.prev; l.item = null; l.prev = null; // help GC last = prev; if (prev == null) first = null; else prev.next = null; size--; modCount++; return element; }
f.删除指定节点
/** * Unlinks non-null node x. */ 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; }
g.根据索引查到指定节点
Node<E> node(int index) { // assert isElementIndex(index); if (index < (size >> 1)) {//如果index小于size的一半从头结点查 Node<E> x = first; for (int i = 0; i < index; i++) x = x.next; return x; } else {//如果index大于size的一半从尾结点开始查 Node<E> x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; } }
2.对外开放的增删改查方法
a.add相关方法
public void addFirst(E e) { linkFirst(e); }
public void addLast(E e) { linkLast(e); }
public boolean add(E e) { linkLast(e); return true; }
public void add(int index, E element) { checkPositionIndex(index);//检测index合法性 if (index == size) linkLast(element); else linkBefore(element, node(index)); }
b.remove相关方法
public E removeFirst() { final Node<E> f = first; if (f == null) throw new NoSuchElementException(); return unlinkFirst(f); }
public E removeLast() { final Node<E> l = last; if (l == null) throw new NoSuchElementException(); return unlinkLast(l); }
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; }
public E remove(int index) { checkElementIndex(index); return unlink(node(index)); }
c.set相关方法
public E set(int index, E element) { checkElementIndex(index);//检查index合法性 Node<E> x = node(index);//拿到index的node E oldVal = x.item; x.item = element; return oldVal; }
d.get的相关方法
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; }
public boolean contains(Object o) { return indexOf(o) != -1; }
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; }
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; }