1.LinkedList
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
//维护一个节点,这个节点包含本身的值,上一节点和下一个节点的指向
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
}
双向链表,可以被当作堆栈、队列或双端队列进行操作。
AbstractSequentialList 实现了get(int index)、set(int index, E element)、add(int index, E element) 和 remove(int index)这些函数。都是随机访问List的,这些方法都是通过接口ListIterator实现的。ListIterator接口继承了Iterator接口,又被LinkedList中的ListItr类实现。
//AbstractSequentialList中的remove方法
public E remove(int index) {
try {
ListIterator<E> e = listIterator(index);
E outCast = e.next();
e.remove();
return outCast;
} catch (NoSuchElementException exc) {
throw new IndexOutOfBoundsException("Index: "+index);
}
}
//接口ListIterator
public interface ListIterator<E> extends Iterator<E>
//LinkedList中的ListItr
private class ListItr implements ListIterator<E>{
public boolean hasNext(){......}
public E next(){....}
.....
}
//使用
public ListIterator<E> listIterator(int index) {
checkPositionIndex(index);
return new ListItr(index);
}
这就是传说中的迭代器模式(Iterator Pattern),ArrayList中也有使用到这个模式。
同时还使用了适配器模式:
2.LinkedBlockingQueue
单向链表实现的阻塞队列,可以定义为无界队列也可以是有界队列。这里用了两个锁,读写可以同时进行,条件满足时,往队尾加入,对头出列。
//维护一个节点,这个节点包含本身的值和下一个节点的指向
static class Node<E> {
E item;
Node<E> next;
Node(E x) { item = x; }
}
private final int capacity;
//使用原子性的AtomicInteger,应该是因为同时可以读写的原因
private final AtomicInteger count = new AtomicInteger();
transient Node<E> head;
private transient Node<E> last;
/** take, poll,peek等读操作的方法需要获取到这个锁 */
private final ReentrantLock takeLock = new ReentrantLock();
/** 如果队列此时为空,还需要队列不为空这个条件 */
private final Condition notEmpty = takeLock.newCondition();
/**put, offer写操作的方法需要获取到这个锁/
private final ReentrantLock putLock = new ReentrantLock();
/** 如果写操作的时候队列是满的,那么等待条件 */
private final Condition notFull = putLock.newCondition();
3.LinkedBlockingDeque
双向链表实现的阻塞队列,可以被当作堆栈、双端队列进行操作。
维护一个节点,这个节点包含本身的值,上一节点和下一个节点的指向
static final class Node<E> {
E item;
Node<E> prev;
Node<E> next;
Node(E x) {
item = x;
}
}
//和ArrayBlockingQueue比较,这里不是使用原子性的
private transient int count;
private final int capacity;
final ReentrantLock lock = new ReentrantLock();
/** Condition for waiting takes */
private final Condition notEmpty = lock.newCondition();
/** Condition for waiting puts */
private final Condition notFull = lock.newCondition();