AbstractSequentialList 抽象類
順序列表,相對於RandomAccess標記接口而言,繼承了RandomAccess接口表示其容器支持隨機訪問,這類容器優先使用索引進行操作,而對於不支持隨機訪問的容器通常使用迭代器進行操作
類聲明
public abstract class AbstractSequentialList<E> extends AbstractList<E>
方法實現
通過迭代器對List的 get()
、add()
、set()
、remove()
方法進行實現
protected AbstractSequentialList() {
}
public E get(int index) {
try {
return listIterator(index).next();
} catch (NoSuchElementException exc) {
throw new IndexOutOfBoundsException("Index: "+index);
}
}
public E set(int index, E element) {
try {
ListIterator<E> e = listIterator(index);
E oldVal = e.next();
e.set(element);
return oldVal;
} catch (NoSuchElementException exc) {
throw new IndexOutOfBoundsException("Index: "+index);
}
}
public void add(int index, E element) {
try {
listIterator(index).add(element);
} catch (NoSuchElementException exc) {
throw new IndexOutOfBoundsException("Index: "+index);
}
}
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);
}
}
public boolean addAll(int index, Collection<? extends E> c) {
try {
boolean modified = false;
ListIterator<E> e1 = listIterator(index);
Iterator<? extends E> e2 = c.iterator();
while (e2.hasNext()) {
e1.add(e2.next());
modified = true;
}
return modified;
} catch (NoSuchElementException exc) {
throw new IndexOutOfBoundsException("Index: "+index);
}
}
// Iterators
public Iterator<E> iterator() {
return listIterator();
}
public abstract ListIterator<E> listIterator(int index);
LinkedList
雙向鏈表結構,線程不安全,增刪快查詢慢
類聲明
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable
基礎單元Node
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;
}
}
重點字段
// 節點數
transient int size = 0;
// 指向頭節點
transient Node<E> first;
// 指向尾節點
transient Node<E> last;
構造函數
// 空參構造
public LinkedList() {
}
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
List方法
(一)添加
// 將指定的元素追加到此鏈表的末尾
public boolean add(E e) {
linkLast(e);
return true;
}
public void add(int index, E element) {
// 校驗索引合理性 index >= 0 && index <= size
checkPositionIndex(index);
if (index == size)
// 如果是最後一個位置,則直接追加到鏈表末尾
linkLast(element);
else
// 否則添加到index節點前面
linkBefore(element, node(index));
}
// 將集合元素添加到鏈表末尾
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c);
}
public boolean addAll(int index, Collection<? extends E> c) {
// 校驗索引的合法性 index >= 0 && index <= size
checkPositionIndex(index);
Object[] a = c.toArray();
int numNew = a.length;
if (numNew == 0)
return false;
// pred是插入位置的前一個節點,succ是插入位置的原節點
Node<E> pred, succ;
if (index == size) {
// 若是在鏈表尾部添加,則last節點爲pred
succ = null;
pred = last;
} else {
// 查找index的節點元素,該元素的前繼節點即爲pred
succ = node(index);
pred = succ.prev;
}
for (Object o : a) {
@SuppressWarnings("unchecked") E e = (E) o;
// 以 pred 作爲前繼節點,e作爲當前元素,null作爲後繼節點構成新節點
Node<E> newNode = new Node<>(pred, e, null);
if (pred == null)
// 如果 pred 爲空則代表新節點插入在頭節點之前,要將頭節點更新爲新節點
first = newNode;
else
// 將前繼節點的下個節點更新爲新節點
pred.next = newNode;
// 將當前節點作爲前繼節點繼續循環
pred = newNode;
}
if (succ == null) {
// 如果是在尾部添加,則將循環的最後一個元素置爲尾元素
last = pred;
} else {
// 否則循環的最後一個元素的下個節點爲succ(插入位置的原節點)
pred.next = succ;
// succ的前繼節點爲循環的最後一個元素
succ.prev = pred;
}
// 更新鏈表大小和修改次數
size += numNew;
modCount++;
return true;
}
(二)刪除
// 調用unlink
public boolean remove(Object o) {
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;
}
// 先找到該索引的元素再調用unlink刪除
public E remove(int index) {
// 校驗索引的合法性 index >= 0 && index < size
checkElementIndex(index);
return unlink(node(index));
}
// 通過for循環將每個節點清空
public void clear() {
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++;
}
(三)修改
// 找到當前節點並修改值
public E set(int index, E element) {
// 校驗索引的合法性 index >= 0 && index < size
checkElementIndex(index);
Node<E> x = node(index);
E oldVal = x.item;
x.item = element;
return oldVal;
}
(三)查詢
public boolean contains(Object o) {
return indexOf(o) != -1;
}
public int size() {
return size;
}
// 通過索引獲取節點
public E get(int index) {
// 校驗索引的合法性 index >= 0 && index < size
checkElementIndex(index);
return node(index).item;
}
// 循環對比 next
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;
}
// 倒序循環對比 prev
public int lastIndexOf(Object o) {
int index = size;
if (o == null) {
for (Node<E> x = last; x != null; x = x.prev) {
index--;
if (x.item == null)
return index;
}
} else {
for (Node<E> x = last; x != null; x = x.prev) {
index--;
if (o.equals(x.item))
return index;
}
}
return -1;
}
// 返回數組副本
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;
}
@SuppressWarnings("unchecked")
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;
}
Deque方法
(一)添加 通過linkFirst、linkLast實現
// 向鏈表頭部添加元素
public void addFirst(E e) {
linkFirst(e);
}
// 向鏈表尾部添加元素
public void addLast(E e) {
linkLast(e);
}
// 入隊
public boolean offer(E e) {
return add(e); // 也是調用linkLast(e)
}
// 隊頭入隊
public boolean offerFirst(E e) {
addFirst(e);
return true;
}
// 隊尾入隊
public boolean offerLast(E e) {
addLast(e);
return true;
}
// 入棧
public void push(E e) {
addFirst(e);
}
(二)刪除 通過unlinkFirst、unlinkLast實現
// 刪除鏈表頭節點
public E remove() {
return removeFirst();
}
// 刪除鏈表頭節點
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);
}
// 出隊
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);
}
// 出棧
public E pop() {
return removeFirst();
}
// 從此deque中刪除指定元素的第一個匹配項 for next
public boolean removeFirstOccurrence(Object o) {
return remove(o);
}
// 從此deque中刪除指定元素的最後一個匹配項 for prev
public boolean removeLastOccurrence(Object o) {
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;
}
(三)查詢
// 獲取第一個元素 頭節點
public E element() {
return getFirst();
}
// 獲取第一個元素 頭節點
public E getFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return f.item;
}
// 獲取最後一個元素 尾節點
public E getLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return l.item;
}
// 返回但不刪除第一個元素 頭節點
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;
}
工具方法
// 查找第index個元素
Node<E> node(int index) {
// index和size中值做對比,如果小於中值則從前往後找,如果大於等於中值則從後往前找
if (index < (size >> 1)) {
Node<E> x = first;
for (int i = 0; i < index; i++)
// 直到找到i=index-1爲止,next指向的下個節點就是需要查找的節點
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--)
// 直到找到i=index+1爲止,next指向的上個節點就是需要查找的節點
x = x.prev;
return x;
}
}
// 將元素添加至鏈表頭部
private void linkFirst(E e) {
// 頭節點
final Node<E> f = first;
// 以 null 作爲前繼節點,e作爲當前元素,f 作爲後繼節點構成新節點
final Node<E> newNode = new Node<>(null, e, f);
// 將頭節點更新爲新節點
first = newNode;
if (f == null)
// 如果鏈表爲null,則將尾節點更新爲新節點,即新節點既是頭節點也是尾結點
last = newNode;
else
// 如果鏈表不爲空,則將原頭節點(現在是第二個節點)前繼節點更新爲新節點
f.prev = newNode;
size++;
modCount++;
}
// 將元素添加至鏈表尾部
void linkLast(E e) {
// 尾結點
final Node<E> l = last;
// 以 l 作爲前繼節點,e作爲當前元素,null作爲後繼節點構成新節點
final Node<E> newNode = new Node<>(l, e, null);
// 將尾結點更新爲新節點
last = newNode;
if (l == null)
// 如果鏈表爲null,則將頭節點更新爲新節點,即新節點既是頭節點也是尾結點
first = newNode;
else
// 如果鏈表不爲空,則將原尾節點(現在是倒數第二個節點)的後繼節點更新爲新節點
l.next = newNode;
// 更新鏈表大小和修改次數
size++;
modCount++;
}
// 在succ節點之前插入元素
void linkBefore(E e, Node<E> succ) {
// assert succ != null;
// succ的原前繼節點
final Node<E> pred = succ.prev;
// 以 pred 作爲前繼節點,e作爲當前元素,succ作爲後繼節點構成新節點
final Node<E> newNode = new Node<>(pred, e, succ);
// 將succ的前繼節點更新爲新節點
succ.prev = newNode;
if (pred == null)
// 如果 pred 爲空則代表新節點插入在頭節點之前,要將頭節點更新爲新節點
first = newNode;
else
// 否則將succ原前繼節點的後繼節點更新爲新節點
pred.next = newNode;
// 更新鏈表大小和修改次數
size++;
modCount++;
}
// 刪除鏈表頭節點
private E unlinkFirst(Node<E> f) {
// 頭節點
final E element = f.item;
// 第二個節點
final Node<E> next = f.next;
f.item = null;
f.next = null; // help GC
// 將頭節點更新爲第二個節點
first = next;
if (next == null)
// 如果第二個節點爲null,代表刪除頭節點後隊列爲空,將尾節點置爲null
last = null;
else
// 否則將第二個節點(新頭節點)的前繼節點置爲null
next.prev = null;
// 更新鏈表大小和修改次數
size--;
modCount++;
return element;
}
// 刪除鏈表尾節點
private E unlinkLast(Node<E> l) {
// 尾節點
final E element = l.item;
// 倒數第二個節點
final Node<E> prev = l.prev;
l.item = null;
l.prev = null; // help GC
// 將尾節點更新爲倒數第二個節點
last = prev;
if (prev == null)
// 如果第倒數二個節點爲null,代表刪除尾節點後隊列爲空,將頭節點置爲null
first = null;
else
// 否則將倒數第二個節點(新尾節點)的後繼節點置爲null
prev.next = null;
// 更新鏈表大小和修改次數
size--;
modCount++;
return element;
}
// 刪除隊列中的某個元素
E unlink(Node<E> x) {
// 當前節點
final E element = x.item;
// 下一個節點
final Node<E> next = x.next;
// 上一個節點
final Node<E> prev = x.prev;
if (prev == null) {
// 如果前置節點爲空,則代表刪除的是頭節點,將頭節點更新爲當前節點的下個節點
first = next;
} else {
// 否則將前置節點的下個節點更新爲當前節點的下個節點
prev.next = next;
// 將當前節點的前置節點置爲null
x.prev = null;
}
if (next == null) {
// 如果後置節點爲空,則代表刪除的是尾節點,將尾節點更新爲當前節點的上個節點
last = prev;
} else {
// 否則將下個節點的前置節點更新爲當前節點的上個節點
next.prev = prev;
// 將當前節點的後置節點置爲null
x.next = null;
}
// 將當前被刪除元素置爲null
x.item = null;
// 更新鏈表大小和修改次數
size--;
modCount++;
return element;
}
序列化
private static final long serialVersionUID = 876323262645176354L;
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
// Write out any hidden serialization magic
s.defaultWriteObject();
// Write out size
s.writeInt(size);
// Write out all elements in the proper order.
for (Node<E> x = first; x != null; x = x.next)
s.writeObject(x.item);
}
@SuppressWarnings("unchecked")
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in any hidden serialization magic
s.defaultReadObject();
// Read in size
int size = s.readInt();
// Read in all elements in the proper order.
for (int i = 0; i < size; i++)
linkLast((E)s.readObject());
}
其餘方法
public ListIterator<E> listIterator(int index) {
checkPositionIndex(index);
return new ListItr(index);
}
private class ListItr implements ListIterator<E> {
...
}
public Iterator<E> descendingIterator() {
return new DescendingIterator();
}
private class DescendingIterator implements Iterator<E> {
...
}
@Override
public Spliterator<E> spliterator() {
return new LLSpliterator<E>(this, -1, 0);
}
static final class LLSpliterator<E> implements Spliterator<E> {
...
}
@SuppressWarnings("unchecked")
private LinkedList<E> superClone() {
try {
return (LinkedList<E>) super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
}
public Object clone() {
LinkedList<E> clone = superClone();
// Put clone into "virgin" state
clone.first = clone.last = null;
clone.size = 0;
clone.modCount = 0;
// Initialize clone with our elements
for (Node<E> x = first; x != null; x = x.next)
clone.add(x.item);
return clone;
}