publicbooleanadd(E e){ //默认尾部添加 linkLast(e); returntrue; } /** * 目标节点创建后寻找前驱节点,前驱节点存在就修改前驱节点的后继,指向目标节点 * @param e */ voidlinkLast(E e){ //获取这个list对象内部的Node类型成员last,即末位节点,以该节点作为新插入元素的前驱节点 final Node<E> l = last; //创建新节点 final Node<E> newNode = new Node<>(l, e, null); //把新节点作为该list对象的最后一个节点 last = newNode; //处理原先的末位节点,如果这个list本来就是一个空的链表 if (l == null) //把新节点作为首节点 first = newNode; else //如果链表内部已经有元素,把原来的末位节点的后继指向新节点,完成链表修改 l.next = newNode; //修改当前list的size size++; //并记录该list对象被执行修改的次数 modCount++; } publicvoidadd(int index, E element){ //检查下标的合法性 checkPositionIndex(index); //插入位置是末位,那还是上面末位添加的逻辑 if (index == size) linkLast(element); else linkBefore(element, node(index)); } privatevoidcheckPositionIndex(int index){ if (!isPositionIndex(index)) thrownew IndexOutOfBoundsException(outOfBoundsMsg(index)); } privatebooleanisPositionIndex(int index){ return index >= 0 && index <= size; } Node<E> node(int index){ //二分查找 index离哪端更近 就从哪端开始找 if (index < (size >> 1)) { Node<E> x = first; for (int i = 0; i < index; i++) //找到index位置的元素 x = x.next; return x; } else { Node<E> x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; } } /** * 指位添加方法核心逻辑 操作新节点 * 紧接修改原有节点的前驱属性,最后再修改前驱节点的后继属性 * @param e * @param succ */ voidlinkBefore(E e, Node<E> succ){ //原位置节点的前驱pred final Node<E> pred = succ.prev; //创建新节点,设置新节点其前驱为原位置节点的前驱pred,其后继为原位置节点succ final Node<E> newNode = new Node<>(pred, e, succ); //将新节点设置到原位置节点的前驱 succ.prev = newNode; //前驱如果为空,空链表,则新节点设置为first if (pred == null) first = newNode; else //将新节点设置到前驱节点的后继 pred.next = newNode; //修改当前list的size size++; //记录该list对象被执行修改的次数。 modCount++; } publicbooleanaddAll(int index, Collection<? extends E> c){ checkPositionIndex(index); //将集合转化为数组 Object[] a = c.toArray(); int numNew = a.length; if (numNew == 0) returnfalse; Node<E> pred, succ; //获取插入节点的前节点(prev)和尾节点(next) 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); if (pred == null) first = newNode; else pred.next = newNode; pred = newNode; } //将 Collection 的链表插入 LinkedList 中。 if (succ == null) { last = pred; } else { pred.next = succ; succ.prev = pred; } size += numNew; modCount++; returntrue; }
删除元素
AbstractSequentialList->remove
public E remove(int index){ checkElementIndex(index); //node(index)找到index位置的元素 return unlink(node(index)); }
/** * remove(Object o)这个删除元素的方法的形参o是数据本身 * 而不是LinkedList集合中的元素(节点) * 所以需要先通过节点遍历的方式,找到o数据对应的元素 * 然后再调用unlink(Node x)方法将其删除 * @param o * @return */ publicbooleanremove(Object o){ if (o == null) { for (Node<E> x = first; x != null; x = x.next) { if (x.item == null) { unlink(x); returntrue; } } } else { for (Node<E> x = first; x != null; x = x.next) { if (o.equals(x.item)) { unlink(x); returntrue; } } } returnfalse; } E unlink(Node<E> x){ //x的数据域element final E element = x.item; //x的下一个结点 final Node<E> next = x.next; //x的上一个结点 final Node<E> prev = x.prev; //如果x的上一个结点是空结点的话,那么说明x是头结点 if (prev == null) { first = next; } else { //将x的前后节点相连双向链表 prev.next = next; //x的属性置空 x.prev = null; } //如果x的下一个结点是空结点的话,那么说明x是尾结点 if (next == null) { last = prev; } else { //将x的前后节点相连 双向链表 next.prev = prev; x.next = null; } //指向null 方便GC回收 x.item = null; size--; modCount++; return element; }
Deque->remove
public E remove(){ return removeFirst(); }
public E removeFirst(){ final Node<E> f = first; if (f == null) thrownew NoSuchElementException(); return unlinkFirst(f); }
private E unlinkFirst(Node<E> f){ final E element = f.item; //获取到头结点的下一个结点 final Node<E> next = f.next; //GC f.item = null; f.next = null; //头指针指向的是头结点的下一个结点 first = next; if (next == null) last = null; else next.prev = null; size--; modCount++; return element; }
public E pop(){ return removeFirst(); } public E removeFirst(){ final Node f = first; if (f == null) thrownew NoSuchElementException(); return unlinkFirst(f); }