publicbooleanaddAll(int index, Collection<? extends E> c) { checkPositionIndex(index);//检查 index 是否越界 index >= 0 && index <= size; Object[] a = c.toArray(); //Collection 转换为数组 intnumNew= a.length; //获取数组长度 if (numNew == 0) //如果数组长度为0则直接返回false returnfalse;
Node<E> pred, succ; //声明前节点,后节点 if (index == size) { //如果是向 LinkedList 末尾添加则后节点=null,前节点设置为原集合最后一个节点 succ = null; pred = last; } else { //获得index处节点作为后置节点,index节点的前节点作为前节点 succ = node(index); pred = succ.prev; }
for (Object o : a) { //遍历数组 @SuppressWarnings("unchecked")Ee= (E) o; Node<E> newNode = newNode<>(pred, e, null); //以前置节点和元素e创建节点 if (pred == null) //如果前置节点是 null,说明是首结点,则将首节点设置为新创建的节点 first = newNode; else//不是首节点,就将前直接点的下一个节点设置为新创建的节点 pred.next = newNode; pred = newNode; //将前节点设置为刚新创建的节点,继续遍历添加... }
voidlinkBefore(E e, Node<E> succ) { // assert succ != null; final Node<E> pred = succ.prev; //原后置节点的前置节点 final Node<E> newNode = newNode<>(pred, e, succ); //创建一个新的节点 succ.prev = newNode; //更改后置节点的前节点指向新节点 if (pred == null) // 如果是在头部添加,需要额外将first设置为新的节点。 first = newNode; else pred.next = newNode; //原前置节点的后置节点指向新节点 size++; modCount++; }
删除元素
remove
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
publicbooleanremove(Object o) { //因为要根据 equeals 方法来判断对象是否是同一个,所以要先判断 Object 是否为空 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) { // assert x != null; finalEelement= x.item; //获得节点x存放的元素 final Node<E> next = x.next; //获得x的后节点 final Node<E> prev = x.prev; //获得x的前节点
if (prev == null) { //如果前节点是空,表示x节点是头结点,移除x后要将 x的后节点设置为头结点 first = next; } else { prev.next = next; //x移除后,将 x 的前节点的后节点不再指向 x,而是指向x的后节点,x也和前节点断开 x.prev = null; }
if (next == null) { //如果后节点是空,表示要被移除的x是末节点,则需要额外将集合的末节点修改设置为 x 的前节点 last = prev; } else { next.prev = prev; // x移除后,将 x 的后节点的前节点不再指向x,而是指向x的前节点,x也和后节点断开 x.next = null; }
x.item = null; //将 x 节点的元素设置为null,便于垃圾回收(GC)。 modCount++; return element; }
删除的方法还有unlinkFirst、unlinkLast比较简单就不阐述了。
更改元素
set
将索引 index 位置上的元素修改
1 2 3 4 5 6 7
public E set(int index, E element) { checkElementIndex(index); //同样是检查index是否越界 index>=0 && index <= size Node<E> x = node(index); //获取 index 节点 EoldVal= x.item; //获取原元素 x.item = element; //替换为新元素 return oldVal; //返回原元素 }
查询
获取目标索引的元素
1 2 3 4
public E get(int index) { checkElementIndex(index); //检查索引是否越界 return node(index).item; //获得 index 节点再获取元素并返回 }
获取 index 节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Node<E> node(int index) { //将结合全部索引二分为两段,判断目标索引是在前一段还是后一段,然后遍历取出 //这里为何不一直用二分法递归取出来呢? if (index < (size >> 1)) { Node<E> x = first; for (inti=0; i < index; i++) x = x.next; return x; } else { Node<E> x = last; for (inti= size - 1; i > index; i--) x = x.prev; return x; } }