java源码阅读LinkedList
1類(lèi)簽名與注釋
public class LinkedList<E>extends AbstractSequentialList<E>implements List<E>, Deque<E>, Cloneable, java.io.Serializable雙向鏈表實(shí)現(xiàn)了List和Deque接口。 實(shí)現(xiàn)所有可選列表操作,并允許所有元素(包括null )。
請(qǐng)注意,此實(shí)現(xiàn)不同步。 如果多個(gè)線(xiàn)程同時(shí)訪(fǎng)問(wèn)鏈接列表,并且至少有一個(gè)線(xiàn)程在結(jié)構(gòu)上修改列表,則必須在外部進(jìn)行同步。 (結(jié)構(gòu)修改是添加或刪除一個(gè)或多個(gè)元素的任何操作;僅設(shè)置元素的值不是結(jié)構(gòu)修改。)這通常通過(guò)在自然封裝列表的對(duì)象上進(jìn)行同步來(lái)實(shí)現(xiàn)。 如果沒(méi)有這樣的對(duì)象存在,列表應(yīng)該使用Collections.synchronizedList方法“包裝”。 這最好在創(chuàng)建時(shí)完成,以防止意外的不同步訪(fǎng)問(wèn)列表:
List list = Collections.synchronizedList(new LinkedList(...));這個(gè)類(lèi)的iterator和listIterator方法返回的迭代器是故障快速的:迭代器創(chuàng)建之后,除了自己的remove和add方法外的任何方法改變了集合的結(jié)構(gòu),迭代器會(huì)拋出ConcurrentModificationException異常。
注意:LinkedList實(shí)現(xiàn)了Deque接口,而Deque又繼承了Queue接口,所以L(fǎng)inkedList可以當(dāng)作隊(duì)列(Queue)來(lái)使用。
?
?
2數(shù)據(jù)結(jié)構(gòu)
LinkedList的基本屬性有三個(gè)
transient int size = 0;transient Node<E> first;transient Node<E> last;size:集合中元素的個(gè)數(shù)
first:鏈表的第一個(gè)節(jié)點(diǎn)
last:鏈表的最后一個(gè)節(jié)點(diǎn)
Node的數(shù)據(jù)結(jié)構(gòu)如下
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;}}Node類(lèi)維護(hù)了本節(jié)點(diǎn)的元素item,以及前向節(jié)點(diǎn)prev和后向節(jié)點(diǎn)next的引用。
?
?
3添加元素
(1)add(E?e)
將指定的元素追加到此列表的末尾。
1 public boolean add(E e) { 2 linkLast(e); 3 return true; 4 } 5 6 void linkLast(E e) { 7 final Node<E> l = last; 8 final Node<E> newNode = new Node<>(l, e, null); 9 last = newNode; 10 if (l == null) 11 first = newNode; 12 else 13 l.next = newNode; 14 size++; 15 modCount++; 16 }?
(2)add(int?index, E?element)
在此列表中的指定位置插入指定的元素。
public void add(int index, E element) {checkPositionIndex(index);if (index == size)linkLast(element);elselinkBefore(element, node(index));}//檢查索引是否越界(0<=index<=size) private void checkPositionIndex(int index) {if (!isPositionIndex(index))throw new IndexOutOfBoundsException(outOfBoundsMsg(index));} private boolean isPositionIndex(int index) {return index >= 0 && index <= size;}//在節(jié)點(diǎn)succ前插入新節(jié)點(diǎn)e 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;elsepred.next = newNode;size++;modCount++;}//返回對(duì)應(yīng)索引位置的節(jié)點(diǎn) Node<E> node(int index) {// assert isElementIndex(index);if (index < (size >> 1)) {Node<E> x = first;for (int i = 0; i < index; i++)x = x.next;return x;} else {Node<E> x = last;for (int i = size - 1; i > index; i--)x = x.prev;return x;}}node方法做了優(yōu)化,當(dāng)index小于size/2時(shí),從first開(kāi)始往后遍歷,否則從last開(kāi)始往前遍歷。這里是一個(gè)簡(jiǎn)單的二分思路。
?
(3)addFirst(E?e)
在該列表開(kāi)頭插入指定的元素。
public void addFirst(E e) {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;elsef.prev = newNode;size++;modCount++;}?
(4)addLast(E?e)
將指定的元素追加到此列表的末尾。 public void addLast(E e) {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;elsel.next = newNode;size++;modCount++;}?
?
4刪除元素
(1)remove()
檢索并刪除此列表的頭(第一個(gè)元素)。 public E remove() {return removeFirst();}public E removeFirst() {final Node<E> f = first;if (f == null)throw new NoSuchElementException();return 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 GCfirst = next;if (next == null)last = null;elsenext.prev = null;size--;modCount++;return element;}?
(2)remove(int?index)
刪除該列表中指定位置的元素。 public E remove(int index) {checkElementIndex(index);return unlink(node(index));}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;} else {prev.next = next;x.prev = null;}if (next == null) {last = prev;} else {next.prev = prev;x.next = null;}x.item = null;size--;modCount++;return element;}?
(3)removeFirst()
從此列表中刪除并返回第一個(gè)元素。
public E removeFirst() {final Node<E> f = first;if (f == null)throw new NoSuchElementException();return unlinkFirst(f);}?
(4)removeLast()
從此列表中刪除并返回最后一個(gè)元素。 public E removeLast() {final Node<E> l = last;if (l == null)throw new NoSuchElementException();return 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 GClast = prev;if (prev == null)first = null;elseprev.next = null;size--;modCount++;return element;}還有其他一些刪除方法(如下所示)這里就不放代碼,感興趣的可以自己去看一下。
boolean remove(Object o) 從列表中刪除指定元素的第一個(gè)出現(xiàn)(如果存在)。 boolean removeFirstOccurrence(Object o) 刪除此列表中指定元素的第一個(gè)出現(xiàn)(從頭到尾遍歷列表時(shí))。 boolean removeLastOccurrence(Object o) 刪除此列表中指定元素的最后一次出現(xiàn)(從頭到尾遍歷列表時(shí))。?
?
5 LinkedList當(dāng)作隊(duì)列使用
(1)入隊(duì) offer
將指定的元素添加為此列表的尾部(最后一個(gè)元素)。
public boolean offer(E e) {return add(e);}offer直接調(diào)用add(e)在隊(duì)列的末尾添加一個(gè)元素。
?
(2)出隊(duì) poll
檢索并刪除此列表的頭(第一個(gè)元素)。 public E poll() {final Node<E> f = first;return (f == null) ? null : unlinkFirst(f);}簡(jiǎn)單使用如下
Queue<Integer> queue = new LinkedList<>(); for(int i = 1 ; i < 5 ; i++){queue.offer(i); } System.out.println(queue.poll()); for(int i : queue){System.out.print(i+" "); }輸出
1 2 3 4?
(3)查看隊(duì)頭元素 peek()
public E peek() {final Node<E> f = first;return (f == null) ? null : f.item;}?
?
6 LinkedList當(dāng)作棧來(lái)使用
(1)入棧 push(E?e)
public void push(E e) {addFirst(e);}?
(2)出棧 pop()
public E pop() {return removeFirst();}?
(3)查看棧頂元素 peek()
public E peek() {final Node<E> f = first;return (f == null) ? null : f.item;}當(dāng)作棧使用的時(shí)候,鏈表的表頭相當(dāng)于棧頂,每次入棧都是往表頭插入,每次出棧都是刪除表頭指向的節(jié)點(diǎn)。簡(jiǎn)單使用如下
LinkedList<Integer> stack = new LinkedList<>(); for(int i = 1 ; i < 5 ; i++){stack.push(i); } System.out.println(stack.pop()); for(int i : stack){System.out.print(i+" "); }輸出
4 3 2 1?
?
7總結(jié)
簡(jiǎn)單來(lái)講,LinkedList就是一個(gè)雙向鏈表。分析一下數(shù)組與鏈表各自的優(yōu)缺點(diǎn),就可以很清楚的知道什么時(shí)候用ArrayList什么時(shí)候該用LinkedList。
鏈表的優(yōu)勢(shì)在于增加和刪除節(jié)點(diǎn)。而數(shù)組的優(yōu)勢(shì)在于遍歷。
轉(zhuǎn)載于:https://www.cnblogs.com/ouym/p/9019501.html
總結(jié)
以上是生活随笔為你收集整理的java源码阅读LinkedList的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 移动端竖屏解决方案
- 下一篇: May 18:PHP 用到的学习工具