LinkedList源码详解
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
LinkedList继承自AbstractSequenceList、实现了List及Deque接口。
AbstractSequenceList提供List接口的骨干实现,以减少实现List接口的复杂度。
Deque是Queue的一个子接口,双向队列是指该队列两端的元素既能入队(offer)也能出队(poll)。
- LinkedList的属性
transient int size = 0; //存储元素的个数
transient Node<E> first; //头节点 //jdk1.6 Entry<E> header = new Entry<E>(null, null, null);
transient Node<E> last; //尾节点
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
- LinkedList的构造方法
public LinkedList() { //jdk1.6 header.next = header.previous = header;带有头结点双向循环链表
} //jkd1.7+ 不带头节点的双向链表
public LinkedList(Collection<? extends E> c) {
this();
addAll(c); //conllection 转换成数组 for循环添加
}
- LinkedList的方法
add方法
public boolean add(E e) {
linkLast(e); //直接添加到尾部
return true;
}
public void add(int index, E element) {
checkPositionIndex(index); //检查下标
if (index == size)
linkLast(element); //是在尾部添加
else //中间插入
linkBefore(element, node(index)); //查找index处的节点,把新节点添加到它的前面
}
private void checkPositionIndex(int index) {
if (!isPositionIndex(index)) //非真就抛异常
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private boolean isPositionIndex(int index) {
return index >= 0 && index <= size; //当于等于0且小于等于当前size的大小
}
void linkLast(E e) { //分2种情况解释 第一次添加 非第一次添加
final Node<E> l = last; //第一次添加last为null 第二次添加last不是null
final Node<E> newNode = new Node<>(l, e, null); //假如第一次添加个String类型的“1” 第二次添加个String类型的“2”
last = newNode; //newNode的item是“1”,newNode.next=null newNode的item是“2”,newNode.next=null
if (l == null) //nowNode.prev=null,并将成员变量last指向newNode nowNode.prev="1"
first = newNode; //因为是第一次添加,l也是null, 第二次添加,l不是null
else //将成员变量frist指向newNode 将当前添加的节点指向上一个节点的next属性
l.next = newNode; //添加后是[null]["1"][null] [null]["1"]["2"][null]
size++; // prve item next prve item next
modCount++;
}
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); //新建一个节点,前面指向succ前面一个借点,后面指向succ
succ.prev = newNode; //succ前面的节点指向新建的节点
if (pred == null) //如果succ前面的节点为空,新建的节点则为头节点
first = newNode;
else
pred.next = newNode; //否则就将前面节点的下一点指向新建的节点
size++;
modCount++;
}
remove方法
public boolean remove(Object o) { //判断要删除的元素是不是null
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));
}
private void checkElementIndex(int index) {
if (!isElementIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private boolean isElementIndex(int index) {
return index >= 0 && index < size;
}
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 { //否则从结尾开始循环
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
E unlink(Node<E> x) {
// assert x != null; //假如LinkerList有这么一组数据[1,2,3,4,5] remove index是0的数据
final E element = x.item; //则节点是1 x.item = 1 next = 2 prev = 3
final Node<E> next = x.next;
final Node<E> prev = x.prev;
if (prev == null) { //prev ==null,2现在就是首节点了
first = next; //这里要注意一点,假如有这么一组数据[1,2,3,null,null,null,8,9],remove index是4
} else { //item prve next 分别为空 ,只是表示指向的内容是null
prev.next = next; //假如删除的不是头结点,将下个节点指向上个节点的下个节点
x.prev = null; //将删除的节点的上个节点指向设置为null
}
if (next == null) {
last = prev;
} else { //接着[1,2,3,4,5]来解释
next.prev = prev; //假如删除的不是尾结点,prve此时是null了,2是首节点,2.prev = null;
x.next = null; //将删除的节点的下个节点指向设置为null
}
x.item = null; //将删除的节点也置为null
size--;
modCount++;
return element;
}
set
public E set(int index, E element) {
checkElementIndex(index); //检查数据下标越界
Node<E> x = node(index); //获取要修改坐标的元素
E oldVal = x.item; //获取这个坐标元素的item属性
x.item = element; //将要修改元素的item属性引用指向element
return oldVal;
}
get
public E get(int index) {
checkElementIndex(index); //检查数据下标越界
return node(index).item; //for循环来取
}
Iterator
private class ListItr implements ListIterator<E> { //正序迭代
private Node<E> lastReturned = null;
private Node<E> next;
private int nextIndex;
private int expectedModCount = modCount;
ListItr(int index) {
next = (index == size) ? null : node(index);
nextIndex = index;
}
public boolean hasNext() {
return nextIndex < size;
}
public E next() {
checkForComodification();
if (!hasNext())
throw new NoSuchElementException();
lastReturned = next;
next = next.next;
nextIndex++;
return lastReturned.item;
}
public boolean hasPrevious() {
return nextIndex > 0;
}
public E previous() {
checkForComodification();
if (!hasPrevious())
throw new NoSuchElementException();
lastReturned = next = (next == null) ? last : next.prev;
nextIndex--;
return lastReturned.item;
}
public int nextIndex() {
return nextIndex;
}
public int previousIndex() {
return nextIndex - 1;
}
public void remove() {
checkForComodification();
if (lastReturned == null)
throw new IllegalStateException();
Node<E> lastNext = lastReturned.next;
unlink(lastReturned);
if (next == lastReturned)
next = lastNext;
else
nextIndex--;
lastReturned = null;
expectedModCount++;
}
public void set(E e) {
if (lastReturned == null)
throw new IllegalStateException();
checkForComodification();
lastReturned.item = e;
}
public void add(E e) {
checkForComodification();
lastReturned = null;
if (next == null)
linkLast(e);
else
linkBefore(e, next);
nextIndex++;
expectedModCount++;
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
private class DescendingIterator implements Iterator<E> { //倒序迭代
private final ListItr itr = new ListItr(size());
public boolean hasNext() {
return itr.hasPrevious();
}
public E next() {
return itr.previous();
}
public void remove() {
itr.remove();
}
}
总结
linkedList基于双向链表实现,有序,允许为null,没有固定容量,不需要扩容。
其中的每个对象包含数据的同时还包含指向链表中前一个与后一个元素的引用。