1 . LinkedList概述:
LinkedList继承了AbstractSequentialList并且实现了List,Deque, Cloneable,java.io.Serializable接口;
LinkedList是双向操作的列表。实现了所有列表操作,并允许包括 null 在内的所有元素。它本身不是同步的,所以当有多个线程操作连表时,我们要自己保证同步线程安全,可以通过它实现:
List list = Collections.synchronizedList(new LinkedList(...));
通过iterator或者listIterator方法,可以得到迭代器iterators,如果再创建迭代器后,再对连表结构进行改变操作,那再调用迭代器的方法时,除了会抛出迭代器本身的异常外,还一定会抛出ConcurrentModificationException异常,因此在多线程环境环境,迭代器会快速失败和清除,以防止在未来产生不确定的问题,行为等。
注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。快速失败迭代器会尽最大努力抛出 ConcurrentModificationException。因此,为提高这类迭代器的正确性而编写一个依赖于此异常的程序是错误的做法:迭代器的快速失败行为应该仅用于检测 bug。
2 . 相关内容
1) 连表的节点对象如下,每个节点对象包含它前者和后者的引用以及它自身的值;
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;
}
}
2) 添加节点到列表头
private void linkFirst(E e) {
final Node<E> f = first;
final Node<E> newNode = new Node<>(null, e, f);
first = newNode;
if (f == null)
last = newNode;
else
f.prev = newNode;
size++;
modCount++;
}
3) 添加节点到列表尾
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++;
}
4) 移除列表头节点
private E unlinkFirst(Node<E> f) {
// assert f == first && f != null;
final E element = f.item;
final Node<E> next = f.next;
f.item = null;
f.next = null; // help GC
first = next;
if (next == null)
last = null;
else
next.prev = null;
size--;
modCount++;
return element;
}
5) 移除列表尾节点
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;
}
3 . 其他知识