日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

Java Review - LinkedList源码解读

發(fā)布時(shí)間:2025/3/21 java 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java Review - LinkedList源码解读 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • Pre
  • 概述
  • 底層數(shù)據(jù)結(jié)構(gòu)-雙向鏈表
  • 源碼解析
    • 構(gòu)造函數(shù)
    • 方法源碼分析
      • getFirst()
      • getLast()
      • remove相關(guān)方法
        • remove(e)
        • remove(index)
        • removeFirst()
        • removeLast()
      • add()
      • addAll()
      • clear()
      • get相關(guān)的方法
      • set()
      • isElementIndex()
      • isPositionIndex()
      • 查找操作
        • indexOf
        • lastIndexOf
  • Queue 方法
  • Deque 方法


Pre

Java Review - ArrayList 源碼解讀


概述

從上圖可知: LinkedList同時(shí)實(shí)現(xiàn)了List接口和Deque接口,既可以看作一個(gè)順序容器,又可以看作一個(gè)隊(duì)列(Queue),同時(shí)又可以看作一個(gè)棧(Stack) 。

當(dāng)需要使用棧或者隊(duì)列時(shí),可以考慮使用LinkedList,一方面是因?yàn)镴ava官方已經(jīng)聲明不建議使用Stack類,更遺憾的是,Java里根本沒(méi)有一個(gè)叫做Queue的類(它是個(gè)接口名字)。

關(guān)于棧或隊(duì)列,現(xiàn)在的首選是ArrayDeque,它有著比LinkedList(當(dāng)作棧或隊(duì)列使用時(shí))有著更好的性能。

ArrayDeque 移步 https://www.nhooo.com/java/java-arraydeque.html


LinkedList的實(shí)現(xiàn)方式?jīng)Q定了所有跟下標(biāo)相關(guān)的操作都是線性時(shí)間,而在首段或者末尾刪除元素只需要常數(shù)時(shí)間。

為追求效率LinkedList沒(méi)有實(shí)現(xiàn)同步(synchronized),如果需要多個(gè)線程并發(fā)訪問(wèn),可以先采用Collections.synchronizedList()方法對(duì)其進(jìn)行包裝。


底層數(shù)據(jù)結(jié)構(gòu)-雙向鏈表

  • LinkedList底層通過(guò)雙向鏈表實(shí)現(xiàn) 。

  • 雙向鏈表的每個(gè)節(jié)點(diǎn)用內(nèi)部類Node表示。LinkedList通過(guò)first和last引用分別指向鏈表的第一個(gè)和最后一個(gè)元素。

  • 沒(méi)有所謂的啞元,當(dāng)鏈表為空的時(shí)候first和last都指向null。


其中Node是私有的內(nèi)部類:


源碼解析

構(gòu)造函數(shù)

/*** Constructs an empty list.*/public LinkedList() {}/*** Constructs a list containing the elements of the specified* collection, in the order they are returned by the collection's* iterator.** @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);}

方法源碼分析

getFirst()

獲取第一個(gè)元素

/*** Returns the first element in this list.** @return the first element in this list* @throws NoSuchElementException if this list is empty*/public E getFirst() {final Node<E> f = first;if (f == null)throw new NoSuchElementException();return f.item;}

getLast()

獲取最后一個(gè)元素

/*** Returns the last element in this list.** @return the last element in this list* @throws NoSuchElementException if this list is empty*/public E getLast() {final Node<E> l = last;if (l == null)throw new NoSuchElementException();return l.item;}


remove相關(guān)方法

有兩個(gè)版本,

  • 一個(gè)是刪除跟指定元素相等的第一個(gè)元素remove(Object o),
  • 一個(gè)是刪除指定下標(biāo)處的元素remove(int index)


remove(e)

【boolean remove(Object o) 】

/*** Removes the first occurrence of the specified element from this list,* if it is present. If this list does not contain the element, it is* unchanged. More formally, removes the element with the lowest index* {@code i} such that* <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>* (if such an element exists). Returns {@code true} if this list* contained the specified element (or equivalently, if this list* changed as a result of the call).** @param o element to be removed from this list, if present* @return {@code true} if this list contained the specified element*/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;} /*** Unlinks non-null node 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) { //刪除的是第一個(gè)元素first = next;} else {prev.next = next;x.prev = null;}if (next == null) {//刪除的是最后一個(gè)元素last = prev;} else {next.prev = prev;x.next = null;}x.item = null;size--;modCount++;return element;}

指的是刪除第一次出現(xiàn)的這個(gè)元素, 如果沒(méi)有這個(gè)元素,則返回false;判讀的依據(jù)是equals方法, 如果equals,則直接unlink這個(gè)node;由于LinkedList可存放null元素,故也可以刪除第一次出現(xiàn)null的元素;


remove(index)

【remove(int index)】

remove(int index)使用的是下標(biāo)計(jì)數(shù), 只需要判斷該index是否有元素即可,如果有則直接unlink這個(gè)node。

/*** Removes the element at the specified position in this list. Shifts any* subsequent elements to the left (subtracts one from their indices).* Returns the element that was removed from the list.** @param index the index of the element to be removed* @return the element previously at the specified position* @throws IndexOutOfBoundsException {@inheritDoc}*/public E remove(int index) {checkElementIndex(index);return unlink(node(index));}


removeFirst()

【刪除 頭部元素】

/*** Removes and returns the first element from this list.** @return the first element from this list* @throws NoSuchElementException if this list is empty*/public E removeFirst() {final Node<E> f = first;if (f == null)throw new NoSuchElementException();return unlinkFirst(f);}/*** Unlinks non-null first node 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;}


removeLast()

/*** Removes and returns the last element from this list.** @return the last element from this list* @throws NoSuchElementException if this list is empty*/public E removeLast() {final Node<E> l = last;if (l == null)throw new NoSuchElementException();return unlinkLast(l);}/*** Unlinks non-null last node 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;}


add()

add()方法有兩個(gè)版本:

  • 一個(gè)是add(E e),該方法在LinkedList的末尾插入元素,因?yàn)橛衛(wèi)ast指向鏈表末尾,在末尾插入元素的花費(fèi)是常數(shù)時(shí)間。只需要簡(jiǎn)單修改幾個(gè)相關(guān)引用即可
  • 另一個(gè)是add(int index, E element),該方法是在指定下表處插入元素,需要先通過(guò)線性查找找到具體位置,然后修改相關(guān)引用完成插入操作。
/*** Appends the specified element to the end of this list.** <p>This method is equivalent to {@link #addLast}.** @param e element to be appended to this list* @return {@code true} (as specified by {@link Collection#add})*/public boolean add(E e) {linkLast(e);return true;}/*** Links e as last element.*/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++;}

add(int index, E element),

  • 當(dāng)index==size時(shí),等同于add(E e);
  • 如果不是,則分兩步: 1.先根據(jù)index找到要插入的位置,即node(index)方法;2.修改引用,完成插入操作。
/*** Inserts the specified element at the specified position in this list.* Shifts the element currently at that position (if any) and any* subsequent elements to the right (adds one to their indices).** @param index index at which the specified element is to be inserted* @param element element to be inserted* @throws IndexOutOfBoundsException {@inheritDoc}*/public void add(int index, E element) {checkPositionIndex(index);if (index == size)linkLast(element);elselinkBefore(element, node(index));}/*** Inserts element e before non-null Node succ.*/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++;}

上面代碼中的node(int index)函數(shù)有一點(diǎn)小小的技巧,因?yàn)殒湵黼p向的,可以從開(kāi)始往后找,也可以從結(jié)尾往前找,具體朝那個(gè)方向找取決于條件index < (size >> 1),也即是index是靠近前端還是后端。

/*** Returns the (non-null) Node at the specified element index.*/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;}}

從這里也可以看出,linkedList通過(guò)index檢索元素的效率沒(méi)有arrayList高


addAll()

addAll(index, c) 實(shí)現(xiàn)方式并不是直接調(diào)用add(index,e)來(lái)實(shí)現(xiàn),主要是因?yàn)樾实膯?wèn)題,另一個(gè)是fail-fast中modCount只會(huì)增加1次;

/*** Appends all of the elements in the specified collection to the end of* this list, in the order that they are returned by the specified* collection's iterator. The behavior of this operation is undefined if* the specified collection is modified while the operation is in* progress. (Note that this will occur if the specified collection is* this list, and it's nonempty.)** @param c collection containing elements to be added to this list* @return {@code true} if this list changed as a result of the call* @throws NullPointerException if the specified collection is null*/public boolean addAll(Collection<? extends E> c) {return addAll(size, c);}/*** Inserts all of the elements in the specified collection into this* list, starting at the specified position. Shifts the element* currently at that position (if any) and any subsequent elements to* the right (increases their indices). The new elements will appear* in the list in the order that they are returned by the* specified collection's iterator.** @param index index at which to insert the first element* from the specified collection* @param c collection containing elements to be added to this list* @return {@code true} if this list changed as a result of the call* @throws IndexOutOfBoundsException {@inheritDoc}* @throws NullPointerException if the specified collection is null*/public boolean addAll(int index, Collection<? extends E> c) {checkPositionIndex(index);Object[] a = c.toArray();int numNew = a.length;if (numNew == 0)return false;Node<E> pred, succ;if (index == size) {succ = null;pred = last;} else {succ = node(index);pred = succ.prev;}for (Object o : a) {@SuppressWarnings("unchecked") E e = (E) o;Node<E> newNode = new Node<>(pred, e, null);if (pred == null)first = newNode;elsepred.next = newNode;pred = newNode;}if (succ == null) {last = pred;} else {pred.next = succ;succ.prev = pred;}size += numNew;modCount++;return true;}


clear()

為了讓GC更快可以回收放置的元素,需要將node之間的引用關(guān)系賦空。

/*** Removes all of the elements from this list.* The list will be empty after this call returns.*/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 Iteratorfor (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++;}

get相關(guān)的方法

【通過(guò)index獲取元素】

// Positional Access Operations/*** Returns the element at the specified position in this list.** @param index index of the element to return* @return the element at the specified position in this list* @throws IndexOutOfBoundsException {@inheritDoc}*/public E get(int index) {checkElementIndex(index);return node(index).item;} /*** Returns the first element in this list.** @return the first element in this list* @throws NoSuchElementException if this list is empty*/public E getFirst() {final Node<E> f = first;if (f == null)throw new NoSuchElementException();return f.item;}/*** Returns the last element in this list.** @return the last element in this list* @throws NoSuchElementException if this list is empty*/public E getLast() {final Node<E> l = last;if (l == null)throw new NoSuchElementException();return l.item;}

get(int index)得到指定下標(biāo)處元素的引用,通過(guò)調(diào)用node(int index)方法實(shí)現(xiàn)


set()

將某個(gè)位置的元素重新賦值。

set(int index, E element)方法將指定下標(biāo)處的元素修改成指定值,也是先通過(guò)node(int index)找到對(duì)應(yīng)下表元素的引用,然后修改Node中item的值

/*** Replaces the element at the specified position in this list with the* specified element.** @param index index of the element to replace* @param element element to be stored at the specified position* @return the element previously at the specified position* @throws IndexOutOfBoundsException {@inheritDoc}*/public E set(int index, E element) {checkElementIndex(index);Node<E> x = node(index);E oldVal = x.item;x.item = element;return oldVal;}

isElementIndex()

/*** Tells if the argument is the index of an existing element.*/private boolean isElementIndex(int index) {return index >= 0 && index < size;}

isPositionIndex()

/*** Tells if the argument is the index of a valid position for an* iterator or an add operation.*/private boolean isPositionIndex(int index) {return index >= 0 && index <= size;}

查找操作

查找操作的本質(zhì)是查找元素的下標(biāo)

indexOf

查找第一次出現(xiàn)的index, 如果找不到返回-1

/*** Returns the index of the first occurrence of the specified element* in this list, or -1 if this list does not contain the element.* More formally, returns the lowest index {@code i} such that* <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,* or -1 if there is no such index.** @param o element to search for* @return the index of the first occurrence of the specified element in* this list, or -1 if this list does not contain the element*/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;}

lastIndexOf

查找最后一次出現(xiàn)的index, 如果找不到返回-1

/*** Returns the index of the last occurrence of the specified element* in this list, or -1 if this list does not contain the element.* More formally, returns the highest index {@code i} such that* <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,* or -1 if there is no such index.** @param o element to search for* @return the index of the last occurrence of the specified element in* this list, or -1 if this list does not contain the element*/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;}


Queue 方法

/*** Retrieves, but does not remove, the head (first element) of this list.** @return the head of this list, or {@code null} if this list is empty* @since 1.5*/public E peek() {final Node<E> f = first;return (f == null) ? null : f.item;}/*** Retrieves, but does not remove, the head (first element) of this list.** @return the head of this list* @throws NoSuchElementException if this list is empty* @since 1.5*/public E element() {return getFirst();}/*** Retrieves and removes the head (first element) of this list.** @return the head of this list, or {@code null} if this list is empty* @since 1.5*/public E poll() {final Node<E> f = first;return (f == null) ? null : unlinkFirst(f);}/*** Retrieves and removes the head (first element) of this list.** @return the head of this list* @throws NoSuchElementException if this list is empty* @since 1.5*/public E remove() {return removeFirst();}/*** Adds the specified element as the tail (last element) of this list.** @param e the element to add* @return {@code true} (as specified by {@link Queue#offer})* @since 1.5*/public boolean offer(E e) {return add(e);}

Deque 方法

/*** Inserts the specified element at the front of this list.** @param e the element to insert* @return {@code true} (as specified by {@link Deque#offerFirst})* @since 1.6*/public boolean offerFirst(E e) {addFirst(e);return true;}/*** Inserts the specified element at the end of this list.** @param e the element to insert* @return {@code true} (as specified by {@link Deque#offerLast})* @since 1.6*/public boolean offerLast(E e) {addLast(e);return true;}/*** Retrieves, but does not remove, the first element of this list,* or returns {@code null} if this list is empty.** @return the first element of this list, or {@code null}* if this list is empty* @since 1.6*/public E peekFirst() {final Node<E> f = first;return (f == null) ? null : f.item;}/*** Retrieves, but does not remove, the last element of this list,* or returns {@code null} if this list is empty.** @return the last element of this list, or {@code null}* if this list is empty* @since 1.6*/public E peekLast() {final Node<E> l = last;return (l == null) ? null : l.item;}/*** Retrieves and removes the first element of this list,* or returns {@code null} if this list is empty.** @return the first element of this list, or {@code null} if* this list is empty* @since 1.6*/public E pollFirst() {final Node<E> f = first;return (f == null) ? null : unlinkFirst(f);}/*** Retrieves and removes the last element of this list,* or returns {@code null} if this list is empty.** @return the last element of this list, or {@code null} if* this list is empty* @since 1.6*/public E pollLast() {final Node<E> l = last;return (l == null) ? null : unlinkLast(l);}/*** Pushes an element onto the stack represented by this list. In other* words, inserts the element at the front of this list.** <p>This method is equivalent to {@link #addFirst}.** @param e the element to push* @since 1.6*/public void push(E e) {addFirst(e);}/*** Pops an element from the stack represented by this list. In other* words, removes and returns the first element of this list.** <p>This method is equivalent to {@link #removeFirst()}.** @return the element at the front of this list (which is the top* of the stack represented by this list)* @throws NoSuchElementException if this list is empty* @since 1.6*/public E pop() {return removeFirst();}/*** Removes the first occurrence of the specified element in this* list (when traversing the list from head to tail). If the list* does not contain the element, it is unchanged.** @param o element to be removed from this list, if present* @return {@code true} if the list contained the specified element* @since 1.6*/public boolean removeFirstOccurrence(Object o) {return remove(o);}/*** Removes the last occurrence of the specified element in this* list (when traversing the list from head to tail). If the list* does not contain the element, it is unchanged.** @param o element to be removed from this list, if present* @return {@code true} if the list contained the specified element* @since 1.6*/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;}

總結(jié)

以上是生活随笔為你收集整理的Java Review - LinkedList源码解读的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。