jdk原始碼閱讀之LinkedList
阿新 • • 發佈:2019-01-11
和ArrayList相似,LinkedList也是實現了List介面,但是LinkedList是用連結串列實現的,而ArrayList是用陣列實現的。兩者的優缺點基本就是連結串列和陣列的優缺點。
先看LinkedList宣告
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
transient int size = 0; transient Node<E> first; transient Node<E> last;
LinkedList是雙向兩頭插入式連結串列,first域引用的是連結串列頭,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不是迴圈連結串列,因此first.prev=null,last.next=null.item域是我們想存放的資料。
LinkedList的增刪查改方法:
1. 增
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)); } 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++; } void linkBefore(E e, Node<E> succ) { // assert succ != null; final Node<E> pred = succ.prev; final Node<E> newNode = new Node<>(pred, e, succ); succ.prev = newNode; if (pred == null) first = newNode; else pred.next = newNode; size++; modCount++; }
對於連結串列,無需擴容,也不需要考慮到容器大小的問題。新增操作基本上是一些指標操作,速度較快。
2. 刪
public E remove(int index) {
checkElementIndex(index);
return unlink(node(index));
}
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);
}
3. 查
public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
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;
}
4. 改
public E set(int index, E element) {
checkElementIndex(index);
Node<E> x = node(index);
E oldVal = x.item;
x.item = element;
return oldVal;
}
5. 遍歷
public ListIterator<E> listIterator(int index) {
checkPositionIndex(index);
return new ListItr(index);
}
public Iterator<E> descendingIterator() {
return new DescendingIterator();
}
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有兩個迭代器,順序相反,其中DescendingIterator 實際上是利用listIterator來實現的。
6. 與ArrayList的轉換
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;
}
這個方法可以將LinkedList轉換成ArrayList