LinkedList简介
双向链表实现 List 和 Deque接口。实现所有可选的列表操作,并允许插入null值。
所有操作的执行方式与双向链表都是一样的。检索操作依据离两端的距离,从开头或结尾开始遍历列表。
此未实现同步,可用List list = Collections.synchronizedList(new LinkedList(...))包装。
LinkedList继承
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
LinkedList源码
一、数据成员
transient int size = 0;
/**
* Pointer to first node.
* Invariant: (first == null && last == null) ||
* (first.prev == null && first.item != null)
*
* 指向第一个节点的指针。不变量:(first == null && last == null)|| (first.prev == null && first.item!= null)
*
*/
transient Node<E> first;
/**
* Pointer to last node.
* Invariant: (first == null && last == null) ||
* (last.next == null && last.item != null)
*
* 指向最后一个节点的指针。不变量:(first == null && last == null)|| (last.next == null && last.item!= null)
*
*/
transient Node<E> last;
二、构造函数
/**
*
*构造一个空列表。
*
*/
public LinkedList() {
}
/**
*
* 按照集合的迭代器返回的顺序构造包含指定集合的元素的列表。
* @param c the collection whose elements are to be placed into this list
* @throws NullPointerException if the specified collection is null
*/
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
三、其他方法
1、linkFirst
链接e作为第一个元素
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++;
}
2、linkLast
链接e作为最后一个元素。
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++;
}
3、unlinkFirst
取消第一个节点f的链接。
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;
}
4、unlinkLast
取消最终节点l的链接。
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;
}
5、unlink
取消链接非空节点x。
E unlink(Node<E> x) {
// assert x != null;
final E element = x.item;
final Node<E> next = x.next;
final Node<E> prev = x.prev;
if (prev == null) {
first = next;//x是头节点,因此头结点变为next
} else {
prev.next = next;
x.prev = null;
}
if (next == null) {
last = prev;
//x是尾节点,因此尾结点变为prev
} else { next.prev = prev; x.next = null; } x.item = null; size--; modCount++; return element; }
6、remove
移除头结点
public E removeFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
}
移除尾节点
public E removeLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return unlinkLast(l);
}
7、add
将指定的元素追加到此列表的头。
public void addFirst(E e) {
linkFirst(e);
}
将指定的元素追加到此列表的末尾。
public void addLast(E e) {
linkLast(e);
}
public boolean add(E e) {
linkLast(e);
return true;
}
8、set
用指定的元素替换此列表中指定位置处的元素。
public E set(int index, E element) {
checkElementIndex(index);
Node<E> x = node(index);
E oldVal = x.item;
x.item = element;
return oldVal;
}
9、clear
从此列表中删除所有元素。此调用返回后,列表将为空。
public void clear() {
// Clearing all of the links between nodes is "unnecessary", but:
// - helps a generational GC if the discarded nodes inhabit
// more than one generation
// - is sure to free memory even if there is a reachable Iterator
for (Node<E> x = first; x != null; ) {
Node<E> next = x.next;
x.item = null;
x.next = null;
x.prev = null;
x = next;
}
first = last = null;
size = 0;
modCount++;
}
10、indexOf
返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。
public int indexOf(Object o) {
int index = 0;
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null)
return index;
index++;
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item))
return index;
index++;
}
}
return -1;
}
11、node
返回指定元素索引处的(非空)节点。
Node<E> node(int index) {
// assert isElementIndex(index);
if (index < (size >> 1)) {//若index<size/2 ,则从头开始
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {若index >= size/2 ,则从尾开始
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
12、peek
检索,但不删除此列表的头(第一个元素)。
public E peek() {
final Node<E> f = first;
return (f == null) ? null : f.item;
}
public E peekFirst() {
final Node<E> f = first;
return (f == null) ? null : f.item;
}
检索,但不删除此列表的尾
public E peekLast() {
final Node<E> l = last;
return (l == null) ? null : l.item;
}
13、element
检索,但不删除此列表的头(第一个元素)。
public E element() {
return getFirst();
}
14、poll
检索并删除此列表的头
public E poll() {
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f);
}
public E pollFirst() {
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f);
}
检索并删除此列表的尾
public E pollLast() {
final Node<E> l = last;
return (l == null) ? null : unlinkLast(l);
}
15、offer
public boolean offer(E e) {
return add(e);//添加到末尾
}
16、offerFirst
在此列表的前面插入指定的元素。
public boolean offerFirst(E e) {
addFirst(e);
return true;
}
17、removeLastOccurrence
删除此列表中指定元素的最后一次出现(从头到尾遍历列表时)。如果列表不包含元素,则不会更改。
if (o == null) {
for (Node<E> x = last; x != null; x = x.prev) {
if (x.item == null) {
unlink(x);
return true;
}
}
} else {
for (Node<E> x = last; x != null; x = x.prev) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}
18、toArray
以正确的顺序返回包含此列表中所有元素的数组(从第一个元素到最后一个元素)。
返回的数组将是"安全的",因为没有对它的引用由此列表维护。 (换句话说,这个方法分配了一个新的数组)。因此调用者可以自由地修改返回的数组。
此方法充当基于阵列和基于集合的API之间的桥梁。
public Object[] toArray() {
Object[] result = new Object[size];
int i = 0;
for (Node<E> x = first; x != null; x = x.next)
result[i++] = x.item;
return result;
}
返回一个包含正确顺序(从第一个元素到最后一个元素)的列表中所有元素的数组。返回的数组的运行时类型是指定数组的运行时类型。如果列表适合指定的数组,则返回其中。
否则,将使用指定数组的运行时类型和此列表的大小分配新数组。
如果列表适合于具有空余空间的指定数组(即,数组具有比列表更多的元素),紧接列表结尾的数组中的元素将设置为{@code null}。
(如果调用者知道列表不包含任何空元素,则这在确定列表</i>的长度时非常有用。)。
与 toArray() 方法类似,此方法充当基于数组和基于集合的API之间的桥梁。此外,该方法允许对输出阵列的运行时类型的精确控制,并且在某些情况下可以用于节省分配成本。
public <T> T[] toArray(T[] a) {
if (a.length < size)
a = (T[])java.lang.reflect.Array.newInstance(
a.getClass().getComponentType(), size);
int i = 0;
Object[] result = a;
for (Node<E> x = first; x != null; x = x.next)
result[i++] = x.item;
if (a.length > size)
a[size] = null;
return a;
}
四、内部类
private class DescendingIterator implements Iterator<E>
private class ListItr extends Itr implements ListIterator<E>
private static class Node<E>
static final class LLSpliterator<E> implements Spliterator<E>
DescendingIterator 是实现了Iterator接口,同时重写了里面的hasNext(),next(),remove()等方法;
ListItr继承Itr,实现了ListIterator接口,同时重写了hasPrevious(),nextIndex(),previousIndex(),previous()等方法。
Node<E> 是链表的节点,拥有成员: E item; Node<E> next; Node<E> prev;
LLSpliterator是一个可分割迭代器,是为了并行遍历元素而设计的一个迭代器,jdk1.8中的集合框架中的数据结构都默认实现了spliterator,具体没怎么了解。