如果插入的位置等于链表的长度就把新增加的元素放在尾部。
Node<E> pred, succ; if (index == size) { succ = null; pred = last; } else { succ = node(index); pred = succ.prev; }最后在循环要插入的元素。这里我们可以看到上面也有modCount。
5.3 addFirst()addFirst是将元素插入到LinkedList的头部。
如果现在的机构是下图的:
addFirst执行的操作就是:
红色是使用addFirst插入后的位置。一下是源码
调用了linkFirst方法。
上面的操作时:
首先执行final Node f = first;将头节点赋值给 f
final Node newNode = new Node<>(null, e, f);将指定元素构造成一个新节点,此节点的指向下一个节点的引用为头节点
//将新节点设为头节点,那么原先的头节点 f 变为第二个节点 first = newNode; //如果第二个节点为空,也就是原先链表是空 if (f == null) //将这个新节点也设为尾节点(前面已经设为头节点了) last = newNode; else f.prev = newNode;//将原先的头节点的上一个节点指向新节点 size++;//节点数加1 modCount++;//和ArrayList中一样记录修改次数 5.4 addLast方法addLast是将元素插入到尾部如图(黄色元素):
黄色node是新增加。注意add也是把元素添加到尾部。我们来看一下源码:
这里看到addLast和add是调用的同一方法,这里就不在讲解。可以看上方的代码。
由于文章比较长分为两次更新。下一篇文章继续分析
上次分析了LinkedList的结构和添加方法这次开始分析下面的。
注意源码版本为JDK1.8
直接进入正题。
1.删除 1.2remove()在LinkedList中remove()和removeFirst()是相同的
在LinkedList中的删除其实就是通过修改上一个节点和指向下一个节点的引用完成的,可以看下面的图片:
我们可以看到把node6的prev指向清空然后把node3的next设置成空就完成了删除的操作。
看一下JDK的源码实现:
调用removeFirst,在调用removeFirst中先获取头部节点,如果头节点为空就抛异常。
调用unlinkFirst private E unlinkFirst(Node<E> f) { final E element = f.item; //next 为头结点的下一个节点 final Node<E> next = f.next; f.item = null; // 将节点的元素以及引用都设为 null,便于垃圾回收 f.next = null; //修改头结点为第二个节点 first = next; //如果第二个节点为空(当前链表只存在第一个元素) if (next == null) //那么尾节点也置为 null last = null; else //如果第二个节点不为空,那么将第二个节点的上一个引用置为 null next.prev = null; size--; modCount++; return element; } 1.3 removeLast()
我们看一下removeLast,从列表中删除最后一个元素
首先看到先获取了last最后一个元素,如果为空然后就抛异常
然后调用了unlinkLast
看到unlinkLast方法中有一个 help gc ,它的主要作用就是帮助GC来做垃圾回收。 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; //帮助GC垃圾回收 l.prev = null; //尾节点为倒数第二个节点 last = prev; //如果倒数第二个节点为null if (prev == null) //那么将节点也置为 null first = null; else prev.next = null; //如果倒数第二个节点不为空,那么将倒数第二个节点的下一个引用置为 null size--; modCount++; return element; }
同样执行了modCount++
1.3 remove(int index)