国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

東陽網(wǎng)站建設(shè)dyfwzx友情鏈接吧

東陽網(wǎng)站建設(shè)dyfwzx,友情鏈接吧,網(wǎng)站建設(shè)的工作描述,東莞技術(shù)支持 駿域網(wǎng)站建設(shè)文章目錄 一、 概述LinkedList1.1 LinkedList簡介1.2 LinkedList的優(yōu)點和缺點 二、 LinkedList數(shù)據(jù)結(jié)構(gòu)分析2.1 Node節(jié)點結(jié)構(gòu)體解析2.2 LinkedList實現(xiàn)了雙向鏈表的原因2.3 LinkedList如何實現(xiàn)了鏈表的基本操作(增刪改查)2.4 LinkedList的遍歷方式 三、 …

在這里插入圖片描述

文章目錄

    • 一、 概述LinkedList
      • 1.1 LinkedList簡介
      • 1.2 LinkedList的優(yōu)點和缺點
    • 二、 LinkedList數(shù)據(jù)結(jié)構(gòu)分析
      • 2.1 Node節(jié)點結(jié)構(gòu)體解析
      • 2.2 LinkedList實現(xiàn)了雙向鏈表的原因
      • 2.3 LinkedList如何實現(xiàn)了鏈表的基本操作(增刪改查)
      • 2.4 LinkedList的遍歷方式
    • 三、 源碼分析
      • 3.1 成員變量
      • 3.2 構(gòu)造方法
      • 3.3 add()方法
      • 3.4 remove()方法
      • 3.5 get()方法
      • 3.6 set()方法
      • 3.7 clear()方法
      • 3.8 indexOf()方法
    • 四、 總結(jié)及實戰(zhàn)應(yīng)用
      • 4.1 LinkedList適用場景
      • 4.2 LinkedList與ArrayList的比較
      • 4.3 LinkedList的使用注意事項
      • 4.4 實戰(zhàn)應(yīng)用:設(shè)計一個基于LinkedList的LRU緩存算法

一、 概述LinkedList

1.1 LinkedList簡介

LinkedList是Java中的一種雙向鏈表數(shù)據(jù)結(jié)構(gòu)實現(xiàn)類,它實現(xiàn)了ListDeque接口。

LinkedList的特點主要包括以下幾點

  1. 鏈表結(jié)構(gòu):LinkedList內(nèi)部使用鏈表來存儲元素,每個節(jié)點都包含當(dāng)前元素的值以及指向前一個節(jié)點和后一個節(jié)點的引用。這種鏈表結(jié)構(gòu)使得插入和刪除元素的操作效率較高。
  2. 雙向訪問:每個節(jié)點都有指向前一個節(jié)點和后一個節(jié)點的引用,這使得在LinkedList中可以通過前向或后向遍歷訪問元素,而不需要像ArrayList那樣進(jìn)行元素的整體移動。
  3. 動態(tài)大小:LinkedList沒有固定的容量限制,可以根據(jù)需要動態(tài)地添加或刪除元素,并且不會出現(xiàn)數(shù)組擴(kuò)容的情況。
  4. 隨機(jī)訪問較慢:由于LinkedList是基于鏈表的數(shù)據(jù)結(jié)構(gòu),因此在訪問特定索引位置的元素時,需要從頭或尾部開始遍歷到目標(biāo)位置。相比之下,ArrayList可以通過索引直接訪問元素,因此在隨機(jī)訪問元素時效率更高。
  5. 支持隊列和棧操作:作為Deque接口的實現(xiàn)類,LinkedList可以被用作隊列(先進(jìn)先出)和棧(后進(jìn)先出)的數(shù)據(jù)結(jié)構(gòu),可以使用addFirst、removeFirst等方法模擬棧操作,使用addLast、removeFirst等方法模擬隊列操作。

總體而言,LinkedList適用于頻繁地插入和刪除元素的場景,但對于隨機(jī)訪問元素的需求不是很高時,可以考慮使用它。

1.2 LinkedList的優(yōu)點和缺點

優(yōu)點

  1. 鏈表的插入和刪除操作比較快速,因為只需要改變指針指向即可。
  2. 可以在任意位置進(jìn)行插入和刪除操作,而不需要像數(shù)組那樣需要移動其他元素。
  3. 在迭代時可以快速獲取下一個元素,因為每個節(jié)點都有指向前后節(jié)點的指針。

缺點

  1. 鏈表的訪問操作比較慢,因為需要遍歷整個鏈表才能找到對應(yīng)的元素。
  2. 由于鏈表每個節(jié)點都需要額外存儲前后節(jié)點的指針,因此占用的內(nèi)存空間比數(shù)組大。
  3. 鏈表沒有像數(shù)組那樣可以直接訪問任意位置的元素,因此不能使用索引隨機(jī)訪問元素。
  4. 當(dāng)需要頻繁進(jìn)行隨機(jī)訪問時,由于缺乏連續(xù)的內(nèi)存空間,可能會導(dǎo)致緩存命中率降低,從而影響性能。

綜上所述,LinkedList 適合在需要頻繁進(jìn)行插入和刪除操作,但是不需要頻繁隨機(jī)訪問元素的場景下使用。如果需要隨機(jī)訪問或者占用空間比較重要時,可以考慮使用其他數(shù)據(jù)結(jié)構(gòu),比如 ArrayList。

二、 LinkedList數(shù)據(jù)結(jié)構(gòu)分析

2.1 Node節(jié)點結(jié)構(gòu)體解析

在Java中,LinkedList的實現(xiàn)是通過一個雙向鏈表來實現(xiàn)的。在LinkedList中,每個節(jié)點都有一個指向前一個節(jié)點和一個指向后一個節(jié)點的引用。

在LinkedList中,Node節(jié)點結(jié)構(gòu)體可以被定義如下

private static class Node<E> {E item;Node<E> next;Node<E> prev;Node(E element, Node<E> next, Node<E> prev) {this.item = element;this.next = next;this.prev = prev;}
}

上面的代碼定義了一個私有靜態(tài)內(nèi)部類Node,該類包含了一個泛型元素item,以及兩個Node類型的引用nextprev,分別表示指向下一個節(jié)點和上一個節(jié)點的引用。此外,Node類還有一個帶有三個參數(shù)的構(gòu)造函數(shù),用于初始化節(jié)點的prev、itemnext屬性。

通過這樣的設(shè)計,LinkedList可以通過Node節(jié)點來構(gòu)建雙向鏈表結(jié)構(gòu),實現(xiàn)了在任意位置進(jìn)行節(jié)點的插入和刪除操作。

2.2 LinkedList實現(xiàn)了雙向鏈表的原因

Java中的LinkedList實現(xiàn)了雙向鏈表是因為雙向鏈表具有以下優(yōu)點

  1. 雙向鏈表可以從前向后或從后向前遍歷,而單向鏈表只能從前往后遍歷,這使得雙向鏈表更加靈活和高效。
  2. 雙向鏈表能夠提供O(1)時間復(fù)雜度的前驅(qū)和后繼節(jié)點訪問操作,而單向鏈表則需要O(n)時間復(fù)雜度的遍歷操作才能找到前驅(qū)節(jié)點。
  3. 雙向鏈表相對于單向鏈表來說,其插入和刪除節(jié)點的操作更加高效,因為只需要改變前后節(jié)點的指針指向即可,而單向鏈表需要先找到前驅(qū)節(jié)點再進(jìn)行操作。

因此,雙向鏈表在實現(xiàn)一些需要頻繁插入和刪除操作的場景下,比單向鏈表更加適用。Java中的LinkedList就是基于雙向鏈表實現(xiàn)的,所以它能夠高效地支持插入、刪除等操作,同時也提供了迭代器和列表迭代器等許多方便的操作。

2.3 LinkedList如何實現(xiàn)了鏈表的基本操作(增刪改查)

在Java中,LinkedList類實現(xiàn)了鏈表的基本操作,包括增加(添加)、刪除、修改和查詢等功能。下面是一些常用的方法:

  1. 添加操作:
    • addFirst(E e):在鏈表的開頭添加元素。
    • addLast(E e):在鏈表的末尾添加元素。
    • add(int index, E element):在指定位置插入元素。
  2. 刪除操作
    • removeFirst():刪除鏈表的第一個元素。
    • removeLast():刪除鏈表的最后一個元素。
    • remove(int index):刪除指定位置的元素。
    • remove(Object o):刪除指定元素。
  3. 修改操作
    • set(int index, E element):將指定位置的元素替換為新的元素。
  4. 查詢操作
    • getFirst():返回鏈表的第一個元素。
    • getLast():返回鏈表的最后一個元素。
    • get(int index):返回指定位置的元素。
    • indexOf(Object o):返回指定元素在鏈表中的索引位置。
    • contains(Object o):判斷鏈表是否包含指定元素。

LinkedList類還提供了其他一些方法用于獲取鏈表的大小、清空鏈表、判斷鏈表是否為空等。

2.4 LinkedList的遍歷方式

在Java中,你可以使用以下幾種方式對LinkedList進(jìn)行遍歷:

1.使用迭代器(Iterator)進(jìn)行遍歷

LinkedList<String> linkedList = new LinkedList<>();
// 假設(shè)已經(jīng)向linkedList中添加了元素
Iterator<String> iterator = linkedList.iterator();
while (iterator.hasNext()) {String element = iterator.next();// 對element進(jìn)行處理
}

2.使用增強(qiáng)型for循環(huán)(foreach)進(jìn)行遍歷

LinkedList<String> linkedList = new LinkedList<>();
// 假設(shè)已經(jīng)向linkedList中添加了元素
for (String element : linkedList) {// 對element進(jìn)行處理
}

這兩種方式都可以用來遍歷LinkedList中的元素,你可以根據(jù)實際情況選擇其中一種來進(jìn)行遍歷操作。

三、 源碼分析

3.1 成員變量

在這里插入圖片描述

3.2 構(gòu)造方法

/*** 默認(rèn)構(gòu)造函數(shù),它不帶任何參數(shù),用來創(chuàng)建一個空的 LinkedList 對象*/
public LinkedList() {
}/*** 帶有參數(shù)的構(gòu)造函數(shù),它接受一個類型為 Collection 的參數(shù) c*/
public LinkedList(Collection<? extends E> c) {// 調(diào)用無參構(gòu)造函數(shù)this();// 將參數(shù) c 中的所有元素添加到新創(chuàng)建的 LinkedList 對象中addAll(c);
}/*** LinkedList 類中的 addAll 方法的定義*/
public boolean addAll(Collection<? extends E> c) {// size表示為當(dāng)前 LinkedList 中的元素數(shù)量// 調(diào)用另一個名為 addAll 的方法來將參數(shù) c 中的所有元素添加到 LinkedList 對象中return addAll(size, c);
}/*** 用于將指定集合中的元素插入到指定位置*/
public boolean addAll(int index, Collection<? extends E> c) {// 檢查索引的有效性,確保索引在范圍內(nèi)checkPositionIndex(index);// 將集合 c 轉(zhuǎn)換為數(shù)組,并將其賦值給對象數(shù)組 aObject[] a = c.toArray();// 獲取新添加元素的數(shù)量int numNew = a.length;// 如果新添加元素的數(shù)量為 0,則直接返回 falseif (numNew == 0)return false;// 定義兩個節(jié)點,pred 表示當(dāng)前節(jié)點的前一個節(jié)點,succ 表示當(dāng)前節(jié)點的后一個節(jié)點LinkedList.Node<E> pred, succ;// 根據(jù)插入位置確定 succ 和 pred 的值// 如果插入位置在末尾,則將 succ 設(shè)置為 null,將 pred 設(shè)置為最后一個節(jié)點if (index == size) {succ = null;pred = last;} else {// 否則,通過 node(index) 方法找到指定位置的節(jié)點,并將其設(shè)置為 succ,同時將其前一個節(jié)點設(shè)置為 predsucc = node(index);pred = succ.prev;}// 遍歷數(shù)組 a 中的元素for (Object o : a) {@SuppressWarnings("unchecked") E e = (E) o;// 將每個元素轉(zhuǎn)換為泛型類型 E,并創(chuàng)建一個新的節(jié)點 newNode,該節(jié)點的前一個節(jié)點為 pred,值為 e,后一個節(jié)點為 nullLinkedList.Node<E> newNode = new LinkedList.Node<>(pred, e, null);// 如果 pred 為 null,則將 newNode 設(shè)置為鏈表的第一個節(jié)點if (pred == null)first = newNode;else// 否則,將 pred 的下一個節(jié)點設(shè)置為 newNodepred.next = newNode;// 將 pred 更新為 newNodepred = newNode;}// 根據(jù) succ 是否為 null 來確定插入后的鏈表結(jié)構(gòu)// 如果 succ 為 null,則表示插入位置在末尾,將 pred 設(shè)置為最后一個節(jié)點if (succ == null) {last = pred;} else {// 否則,將 pred 的下一個節(jié)點設(shè)置為 succ,并將 succ 的前一個節(jié)點設(shè)置為 predpred.next = succ;succ.prev = pred;}// 更新鏈表的大小和修改計數(shù)器size += numNew;modCount++;// 返回 true,表示添加操作成功完成return true;
}

3.3 add()方法

/*** 用于向鏈表末尾添加一個元素 e*/
public boolean add(E e) {// 將元素 e 添加到鏈表的末尾linkLast(e);// 添加操作成功return true;
}/*** 向鏈表末尾添加一個元素的操作*/
void linkLast(E e) {// 創(chuàng)建一個名為 l 的局部變量,用于保存當(dāng)前鏈表的最后一個節(jié)點的引用,通過訪問 last 字段獲取最后一個節(jié)點的引用final LinkedList.Node<E> l = last;// 創(chuàng)建一個新的節(jié)點 newNode,并將其初始化為一個具有前驅(qū)節(jié)點為 l、元素為 e、后繼節(jié)點為 null 的節(jié)點final LinkedList.Node<E> newNode = new LinkedList.Node<>(l, e, null);// 將鏈表的 last 指針指向新的節(jié)點 newNode,使其成為最后一個節(jié)點last = newNode;// 如果 l 為空(即鏈表為空),則將鏈表的 first 指針指向新的節(jié)點 newNode,否則將 l 節(jié)點的后繼節(jié)點指向新的節(jié)點 newNodeif (l == null)first = newNode;elsel.next = newNode;// 增加鏈表的大小,將鏈表中元素的數(shù)量加1size++;// 增加修改計數(shù)器 modCount 的值,用于追蹤鏈表結(jié)構(gòu)的修改次數(shù)modCount++;
}

3.4 remove()方法

/*** 用于從 LinkedList 中刪除指定的元素*/
public boolean remove(Object o) {// 判斷傳入的參數(shù) o 是否為 null// 如果 o 為 null,則說明要刪除的元素是 null 值if (o == null) {// 因此需要遍歷 LinkedList 中的所有節(jié)點并查找 item 屬性為 null 的節(jié)點// 循環(huán)體中的變量 x 表示當(dāng)前正在遍歷的節(jié)點,初始化為 first(即頭節(jié)點),在每次迭代后更新為下一個節(jié)點,直到遍歷完整個 LinkedListfor (LinkedList.Node<E> x = first; x != null; x = x.next) {// 如果當(dāng)前節(jié)點的 item 屬性為 null(在 o 為 null 的情況下),則調(diào)用輔助方法 unlink 刪除該節(jié)點并返回 trueif (x.item == null) {unlink(x);return true;}}} else {// 否則需要遍歷所有節(jié)點并查找 item 屬性等于 o 的節(jié)點for (LinkedList.Node<E> x = first; x != null; x = x.next) {// 如果當(dāng)前節(jié)點的 item 屬性等于 o(在 o 不為 null 的情況下),則調(diào)用輔助方法 unlink 刪除該節(jié)點并返回 trueif (o.equals(x.item)) {unlink(x);return true;}}}return false;
}/*** 這是一個輔助方法,用于刪除指定節(jié)點 x*/
E unlink(LinkedList.Node<E> x) {// assert x != null;// 保存被刪除節(jié)點的元素值final E element = x.item;// 存儲被刪除節(jié)點的前驅(qū)和后繼節(jié)點final LinkedList.Node<E> next = x.next;final LinkedList.Node<E> prev = x.prev;// 如果被刪除節(jié)點是頭節(jié)點,則將頭指針指向其后繼節(jié)點if (prev == null) {first = next;} else {// 否則更新被刪除節(jié)點的前驅(qū)節(jié)點的 next 屬性為其后繼節(jié)點,并將被刪除節(jié)點的 prev 屬性設(shè)為 nullprev.next = next;x.prev = null;}// 如果被刪除節(jié)點是尾節(jié)點,則將尾指針指向其前驅(qū)節(jié)點if (next == null) {last = prev;} else {// 否則更新被刪除節(jié)點的后繼節(jié)點的 prev 屬性為其前驅(qū)節(jié)點,并將被刪除節(jié)點的 next 屬性設(shè)為 nullnext.prev = prev;x.next = null;}// 將被刪除節(jié)點的 item 屬性設(shè)為 nullx.item = null;// 更新 LinkedList 的元素數(shù)量和修改次數(shù)size--;modCount++;// 返回被刪除節(jié)點的元素值return element;
}

3.5 get()方法

/*** 用于獲取指定索引處的元素*/
public E get(int index) {// 檢查索引的有效性,然后調(diào)用另一個私有輔助方法 node 來獲取對應(yīng)索引處的節(jié)點checkElementIndex(index);// 返回該節(jié)點的元素值return node(index).item;
}/*** 檢查指定索引是否在有效范圍內(nèi)*/
private void checkElementIndex(int index) {// 調(diào)用 isElementIndex 方法來判斷索引是否在有效范圍內(nèi)if (!isElementIndex(index))// 如果不在,則拋出 IndexOutOfBoundsException 異常,異常消息由 outOfBoundsMsg 方法返回throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}/*** 判斷指定索引是否在有效范圍內(nèi)*/
private boolean isElementIndex(int index) {// 如果索引大于等于 0 并且小于 size,則返回 true;否則返回 falsereturn index >= 0 && index < size;
}

3.6 set()方法

/*** 用于將指定索引(index)位置的元素替換為新的元素,并返回被替換掉的舊元素*/
public E set(int index, E element) {// 用于將指定索引(index)位置的元素替換為新的元素,并返回被替換掉的舊元素checkElementIndex(index);// 獲取指定索引位置上的節(jié)點LinkedList.Node<E> x = node(index);// 將指定索引位置上的節(jié)點的元素值賦給變量 oldVal,即記錄舊元素的值E oldVal = x.item;// 將指定索引位置上的節(jié)點的元素值替換為新的元素值 elementx.item = element;// 返回被替換掉的舊元素值return oldVal;
}/*** 檢查指定索引是否在有效范圍內(nèi)*/
private void checkElementIndex(int index) {// 調(diào)用 isElementIndex 方法來判斷索引是否在有效范圍內(nèi)if (!isElementIndex(index))// 如果不在,則拋出 IndexOutOfBoundsException 異常,異常消息由 outOfBoundsMsg 方法返回throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}/*** 判斷指定索引是否在有效范圍內(nèi)*/
private boolean isElementIndex(int index) {// 如果索引大于等于 0 并且小于 size,則返回 true;否則返回 falsereturn index >= 0 && index < size;
}

3.7 clear()方法

/*** 用于清空整個鏈表的內(nèi)容,并釋放相關(guān)的內(nèi)存空間*/
public void clear() {// Clearing all of the links between nodes is "unnecessary", but:// 解釋了清除所有節(jié)點之間鏈接的操作雖然“不必要”,但有兩個原因:// - helps a generational GC if the discarded nodes inhabit// 幫助分代垃圾回收(generational GC)//   more than one generation// - is sure to free memory even if there is a reachable Iterator// 和確保釋放內(nèi)存即使存在可達(dá)的迭代器// 循環(huán)體中的變量 x 初始化為頭節(jié)點 first,然后在每次迭代中更新為下一個節(jié)點,直到遍歷完整個鏈表for (LinkedList.Node<E> x = first; x != null; ) {// 用于保存當(dāng)前節(jié)點 x 的后繼節(jié)點的引用,以防止在清空當(dāng)前節(jié)點之后丟失對后繼節(jié)點的引用LinkedList.Node<E> next = x.next;// 將當(dāng)前節(jié)點 x 的元素值、前驅(qū)節(jié)點和后繼節(jié)點都設(shè)置為 null,從而切斷當(dāng)前節(jié)點與前后節(jié)點的關(guān)聯(lián)x.item = null;x.next = null;x.prev = null;// 將 x 更新為下一個節(jié)點,以便進(jìn)行下一次循環(huán)迭代x = next;}// 清空頭節(jié)點和尾節(jié)點的引用,使整個鏈表為空first = last = null;// 將鏈表的大小設(shè)置為 0,表示鏈表中不再包含任何元素size = 0;// 更新修改次數(shù)計數(shù)器,用于在迭代過程中檢測并發(fā)修改modCount++;
}

3.8 indexOf()方法

/*** 用于查找指定元素在鏈表中第一次出現(xiàn)的位置(索引)*/
public int indexOf(Object o) {// 初始化索引變量為 0,表示從頭節(jié)點開始查找int index = 0;// 如果要查找的元素 o 是 null,則執(zhí)行下面的 for 循環(huán),按順序遍歷鏈表,查找第一個元素值為 null 的節(jié)點if (o == null) {// 變量 x 初始化為頭節(jié)點 first,然后在每次迭代中更新為下一個節(jié)點,直到遍歷完整個鏈表for (LinkedList.Node<E> x = first; x != null; x = x.next) {// 判斷當(dāng)前節(jié)點 x 的元素值是否為 null,如果是,則說明找到了要查找的元素,返回當(dāng)前索引 index 表示該元素在鏈表中的位置if (x.item == null)return index;// 如果當(dāng)前節(jié)點不是要查找的元素,則將索引變量 index 加 1,繼續(xù)向下查找index++;}} else {// 如果要查找的元素 o 不是 null,則執(zhí)行下面的 for 循環(huán),按順序遍歷鏈表,查找第一個元素值與 o 相等的節(jié)點for (LinkedList.Node<E> x = first; x != null; x = x.next) {// 判斷當(dāng)前節(jié)點 x 的元素值是否與要查找的元素 o 相等,如果是,則說明找到了要查找的元素,返回當(dāng)前索引 index 表示該元素在鏈表中的位置if (o.equals(x.item))return index;// 如果當(dāng)前節(jié)點不是要查找的元素,則將索引變量 index 加 1,繼續(xù)向下查找index++;}}// 如果整個鏈表都遍歷完了還沒有找到要查找的元素,則返回 -1,表示該元素不存在于鏈表中return -1;
}

四、 總結(jié)及實戰(zhàn)應(yīng)用

4.1 LinkedList適用場景

LinkedList在Java中適用于以下場景

  1. 需要頻繁進(jìn)行插入和刪除操作:由于LinkedList是基于鏈表結(jié)構(gòu)實現(xiàn)的,插入和刪除操作的時間復(fù)雜度為O(1),因此適合在需要頻繁執(zhí)行這些操作的場景下使用。
  2. 需要實現(xiàn)隊列(Queue)或雙端隊列(Deque)功能:LinkedList實現(xiàn)了QueueDeque接口,可以作為隊列或雙端隊列來使用。
  3. 不需要頻繁進(jìn)行隨機(jī)訪問:由于LinkedList對于隨機(jī)訪問的效率較低,如果不需要頻繁通過索引來訪問元素,而是更多地進(jìn)行順序訪問或者在頭尾進(jìn)行操作,那么LinkedList比較適合。
  4. 對內(nèi)存占用沒有過高要求:相比于ArrayList,在一些情況下,由于它的存儲結(jié)構(gòu),LinkedList可能會占用更多的內(nèi)存空間。

需要注意的是,在某些特定的場景下,可能需要根據(jù)具體的需求進(jìn)行性能測試和選擇,以確定使用LinkedList是否能夠帶來性能上的提升。

4.2 LinkedList與ArrayList的比較

LinkedList和ArrayList是Java中兩種常見的集合實現(xiàn)類,它們具有一些不同的特點和適用場景。

LinkedList的特點

  • 基于雙向鏈表實現(xiàn),每個節(jié)點都包含指向前一個節(jié)點和后一個節(jié)點的引用。
  • 高效地支持插入和刪除操作,因為只需要改變前后節(jié)點的指針指向即可。
  • 在使用迭代器進(jìn)行遍歷時,效率較高。
  • 對于頻繁的插入和刪除操作,LinkedList通常比ArrayList更加高效。

ArrayList的特點

  • 基于動態(tài)數(shù)組實現(xiàn),內(nèi)部使用數(shù)組來存儲元素。
  • 支持隨機(jī)訪問,通過索引可以快速訪問元素。
  • 在獲取元素和遍歷操作方面,ArrayList相對更高效。
  • 對于需要頻繁隨機(jī)訪問元素的操作,ArrayList通常比LinkedList更加高效。

綜上所述,選擇LinkedList還是ArrayList取決于具體的使用場景和需求

  • 如果需要頻繁進(jìn)行插入和刪除操作,而對于隨機(jī)訪問的需求較少,則選擇LinkedList更合適。
  • 如果需要頻繁進(jìn)行隨機(jī)訪問,插入和刪除操作相對較少,則選擇ArrayList更合適。

需要注意的是,在多線程環(huán)境下,LinkedList和ArrayList都不是線程安全的,如果需要在多線程環(huán)境下使用,需要進(jìn)行適當(dāng)?shù)耐教幚砘蚴褂镁€程安全的集合類。

4.3 LinkedList的使用注意事項

在使用 Java 中的 LinkedList 時,有一些需要注意的事項,包括但不限于以下幾點:

  1. 插入和刪除效率高:LinkedList 在插入和刪除操作上有較高的效率,因為它基于雙向鏈表實現(xiàn)。因此,在需要頻繁進(jìn)行插入和刪除操作的場景下,可以考慮使用 LinkedList。
  2. 隨機(jī)訪問效率低:相比于 ArrayList,LinkedList 對于隨機(jī)訪問的效率較低,因為要通過指針一個個地找到目標(biāo)位置。因此,在需要頻繁進(jìn)行隨機(jī)訪問的場景下,最好選擇 ArrayList。
  3. 迭代器遍歷高效:LinkedList 的迭代器遍歷效率較高,可以高效地進(jìn)行前向和后向遍歷操作。
  4. 注意空間開銷:由于 LinkedList 中每個節(jié)點都需要存儲額外的指針信息,因此相比于 ArrayList,它在存儲同樣數(shù)量的元素時會占用更多的內(nèi)存空間。
  5. 不是線程安全的:LinkedList 不是線程安全的,如果需要在多線程環(huán)境中使用,需要進(jìn)行適當(dāng)?shù)耐教幚砘蚩紤]使用線程安全的集合類。
  6. 謹(jǐn)慎使用大數(shù)據(jù)量:在處理大數(shù)據(jù)量的情況下,由于 LinkedList 涉及頻繁的節(jié)點創(chuàng)建和指針操作,可能會導(dǎo)致性能下降,需要謹(jǐn)慎使用。

綜上所述,使用 LinkedList 時需要根據(jù)具體的場景和需求進(jìn)行權(quán)衡,特別是在涉及到插入、刪除、遍歷和空間占用等方面需要特別留意。

4.4 實戰(zhàn)應(yīng)用:設(shè)計一個基于LinkedList的LRU緩存算法

LRU(Least Recently Used)算法是一種緩存置換策略,它根據(jù)數(shù)據(jù)最近被訪問的時間來決定哪些數(shù)據(jù)會被保留,哪些數(shù)據(jù)會被淘汰。在 Java 中,可以通過 LinkedList HashMap 來實現(xiàn) LRU 緩存算法。

具體實現(xiàn)步驟如下

1.定義一個雙向鏈表和一個哈希表,用于存儲緩存數(shù)據(jù)和快速定位數(shù)據(jù)。

private class CacheNode {private String key;private Object value;private CacheNode prev;private CacheNode next;public CacheNode(String key, Object value) {this.key = key;this.value = value;}
}private Map<String, CacheNode> cacheMap;
private CacheNode head;
private CacheNode tail;
private int capacity;

2.在構(gòu)造函數(shù)中初始化雙向鏈表和哈希表,并設(shè)置緩存容量。

public LRUCache(int capacity) {this.capacity = capacity;cacheMap = new HashMap<>(capacity);head = new CacheNode(null, null);tail = new CacheNode(null, null);head.next = tail;tail.prev = head;
}

3.實現(xiàn) get 方法,每次獲取數(shù)據(jù)時,將數(shù)據(jù)移到鏈表頭部,并更新哈希表中的位置信息。

public Object get(String key) {CacheNode node = cacheMap.get(key);if (node == null) {return null;}// 將節(jié)點移動到鏈表頭部moveToHead(node);return node.value;
}private void moveToHead(CacheNode node) {// 先將節(jié)點從原有位置刪除removeNode(node);// 將節(jié)點插入到鏈表頭部insertNodeAtHead(node);
}private void removeNode(CacheNode node) {node.prev.next = node.next;node.next.prev = node.prev;
}private void insertNodeAtHead(CacheNode node) {node.next = head.next;node.next.prev = node;head.next = node;node.prev = head;
}

4.實現(xiàn) put 方法,每次存儲數(shù)據(jù)時,如果緩存已滿,則淘汰鏈表尾部的數(shù)據(jù),并在哈希表中刪除相應(yīng)的位置信息。

public void put(String key, Object value) {CacheNode node = cacheMap.get(key);if (node != null) {// 如果鍵已經(jīng)存在,則更新值,并移到鏈表頭部node.value = value;moveToHead(node);} else {// 如果鍵不存在,則插入新節(jié)點到鏈表頭部,并添加位置信息到哈希表node = new CacheNode(key, value);cacheMap.put(key, node);insertNodeAtHead(node);if (cacheMap.size() > capacity) {// 如果緩存已滿,則淘汰鏈表尾部的節(jié)點,并刪除相應(yīng)位置信息CacheNode removedNode = removeNodeAtTail();cacheMap.remove(removedNode.key);}}
}private CacheNode removeNodeAtTail() {CacheNode removedNode = tail.prev;removeNode(removedNode);return removedNode;
}

這樣,一個基于 LinkedList 的 LRU 緩存算法就實現(xiàn)了。

可以通過如下代碼進(jìn)行簡單的測試

LRUCache cache = new LRUCache(2);
cache.put("A", 1);
cache.put("B", 2);
System.out.println(cache.get("A")); // 輸出 1
cache.put("C", 3);
System.out.println(cache.get("B")); // 輸出 null

盈若安好,便是晴天

http://m.aloenet.com.cn/news/44111.html

相關(guān)文章:

  • 沈陽網(wǎng)站建設(shè)建設(shè)公司排名優(yōu)化seo系統(tǒng)
  • 重慶網(wǎng)站設(shè)計公司價格丈哥seo博客工具
  • 如何搭建一個個人網(wǎng)站學(xué)校招生網(wǎng)絡(luò)營銷方案
  • 給公司網(wǎng)站設(shè)計寧波廠家關(guān)鍵詞優(yōu)化
  • 智聯(lián)招聘網(wǎng)站建設(shè)情況注冊城鄉(xiāng)規(guī)劃師好考嗎
  • jqueryui做的網(wǎng)站株洲seo排名
  • 寧波做網(wǎng)站的大公司排名關(guān)鍵詞搜索推廣排行榜
  • 如何免費網(wǎng)站建設(shè)怎么可以在百度發(fā)布信息
  • 做網(wǎng)站運營的女生多嗎百度公司簡介
  • 上海小微企業(yè)名錄查詢seo短視頻網(wǎng)頁入口營銷
  • 公司網(wǎng)站建設(shè)北京北京做百度推廣的公司
  • 網(wǎng)站開發(fā)用啥語言廣州各區(qū)正在進(jìn)一步優(yōu)化以下措施
  • 順德做網(wǎng)站公司seo搜狗
  • 網(wǎng)站后端怎么做河北網(wǎng)站建設(shè)公司排名
  • 手機(jī)模板網(wǎng)站模板鞏義網(wǎng)站優(yōu)化公司
  • 網(wǎng)頁的動態(tài)效果網(wǎng)店關(guān)鍵詞怎么優(yōu)化
  • 自己做網(wǎng)站需要服務(wù)器培訓(xùn)機(jī)構(gòu)查詢網(wǎng)
  • 自助申請海外網(wǎng)站長沙網(wǎng)絡(luò)公關(guān)公司
  • 傳統(tǒng)營銷渠道有哪些seo網(wǎng)站排名優(yōu)化培訓(xùn)教程
  • 網(wǎng)站建設(shè)及推廣銷售話術(shù)新app推廣方案
  • 衡陽公司做網(wǎng)站關(guān)鍵詞分類
  • 北京好的網(wǎng)站開發(fā)網(wǎng)站推廣 方法
  • 北京十佳網(wǎng)站建設(shè)廣告網(wǎng)站大全
  • 唐山住房和城鄉(xiāng)建設(shè)廳網(wǎng)站谷歌外貿(mào)seo
  • 景區(qū)網(wǎng)站建設(shè)教程如何免費發(fā)布廣告
  • 網(wǎng)站開發(fā)公司總匯seo基礎(chǔ)知識培訓(xùn)視頻
  • 購物商城開發(fā)seo優(yōu)化設(shè)計
  • 大連重工 央企江西seo推廣軟件
  • 音樂網(wǎng)站開發(fā)的目的杭州百度推廣代理公司哪家好
  • 網(wǎng)站建設(shè)教程 pdf營銷型網(wǎng)站建設(shè)論文