中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

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

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

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

在這里插入圖片描述

文章目錄

    • 一、 概述LinkedList
      • 1.1 LinkedList簡(jiǎn)介
      • 1.2 LinkedList的優(yōu)點(diǎn)和缺點(diǎn)
    • 二、 LinkedList數(shù)據(jù)結(jié)構(gòu)分析
      • 2.1 Node節(jié)點(diǎn)結(jié)構(gòu)體解析
      • 2.2 LinkedList實(shí)現(xiàn)了雙向鏈表的原因
      • 2.3 LinkedList如何實(shí)現(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é)及實(shí)戰(zhàn)應(yīng)用
      • 4.1 LinkedList適用場(chǎng)景
      • 4.2 LinkedList與ArrayList的比較
      • 4.3 LinkedList的使用注意事項(xiàng)
      • 4.4 實(shí)戰(zhàn)應(yīng)用:設(shè)計(jì)一個(gè)基于LinkedList的LRU緩存算法

一、 概述LinkedList

1.1 LinkedList簡(jiǎn)介

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

LinkedList的特點(diǎn)主要包括以下幾點(diǎn)

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

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

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

優(yōu)點(diǎn)

  1. 鏈表的插入和刪除操作比較快速,因?yàn)橹恍枰淖冎羔樦赶蚣纯伞?/li>
  2. 可以在任意位置進(jìn)行插入和刪除操作,而不需要像數(shù)組那樣需要移動(dòng)其他元素。
  3. 在迭代時(shí)可以快速獲取下一個(gè)元素,因?yàn)槊總€(gè)節(jié)點(diǎn)都有指向前后節(jié)點(diǎn)的指針。

缺點(diǎn)

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

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

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

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

在Java中,LinkedList的實(shí)現(xiàn)是通過(guò)一個(gè)雙向鏈表來(lái)實(shí)現(xiàn)的。在LinkedList中,每個(gè)節(jié)點(diǎn)都有一個(gè)指向前一個(gè)節(jié)點(diǎn)和一個(gè)指向后一個(gè)節(jié)點(diǎn)的引用。

在LinkedList中,Node節(jié)點(diǎn)結(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;}
}

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

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

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

Java中的LinkedList實(shí)現(xiàn)了雙向鏈表是因?yàn)?strong>雙向鏈表具有以下優(yōu)點(diǎn):

  1. 雙向鏈表可以從前向后或從后向前遍歷,而單向鏈表只能從前往后遍歷,這使得雙向鏈表更加靈活和高效。
  2. 雙向鏈表能夠提供O(1)時(shí)間復(fù)雜度的前驅(qū)和后繼節(jié)點(diǎn)訪問(wèn)操作,而單向鏈表則需要O(n)時(shí)間復(fù)雜度的遍歷操作才能找到前驅(qū)節(jié)點(diǎn)。
  3. 雙向鏈表相對(duì)于單向鏈表來(lái)說(shuō),其插入和刪除節(jié)點(diǎn)的操作更加高效,因?yàn)橹恍枰淖兦昂蠊?jié)點(diǎn)的指針指向即可,而單向鏈表需要先找到前驅(qū)節(jié)點(diǎn)再進(jìn)行操作。

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

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

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

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

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

2.4 LinkedList的遍歷方式

在Java中,你可以使用以下幾種方式對(duì)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();// 對(duì)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) {// 對(duì)element進(jìn)行處理
}

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

三、 源碼分析

3.1 成員變量

在這里插入圖片描述

3.2 構(gòu)造方法

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

3.3 add()方法

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

3.4 remove()方法

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

3.5 get()方法

/*** 用于獲取指定索引處的元素*/
public E get(int index) {// 檢查索引的有效性,然后調(diào)用另一個(gè)私有輔助方法 node 來(lái)獲取對(duì)應(yīng)索引處的節(jié)點(diǎn)checkElementIndex(index);// 返回該節(jié)點(diǎn)的元素值return node(index).item;
}/*** 檢查指定索引是否在有效范圍內(nèi)*/
private void checkElementIndex(int index) {// 調(diào)用 isElementIndex 方法來(lái)判斷索引是否在有效范圍內(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é)點(diǎn)LinkedList.Node<E> x = node(index);// 將指定索引位置上的節(jié)點(diǎn)的元素值賦給變量 oldVal,即記錄舊元素的值E oldVal = x.item;// 將指定索引位置上的節(jié)點(diǎn)的元素值替換為新的元素值 elementx.item = element;// 返回被替換掉的舊元素值return oldVal;
}/*** 檢查指定索引是否在有效范圍內(nèi)*/
private void checkElementIndex(int index) {// 調(diào)用 isElementIndex 方法來(lái)判斷索引是否在有效范圍內(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()方法

/*** 用于清空整個(gè)鏈表的內(nèi)容,并釋放相關(guān)的內(nèi)存空間*/
public void clear() {// Clearing all of the links between nodes is "unnecessary", but:// 解釋了清除所有節(jié)點(diǎn)之間鏈接的操作雖然“不必要”,但有兩個(gè)原因:// - 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é)點(diǎn) first,然后在每次迭代中更新為下一個(gè)節(jié)點(diǎn),直到遍歷完整個(gè)鏈表for (LinkedList.Node<E> x = first; x != null; ) {// 用于保存當(dāng)前節(jié)點(diǎn) x 的后繼節(jié)點(diǎn)的引用,以防止在清空當(dāng)前節(jié)點(diǎn)之后丟失對(duì)后繼節(jié)點(diǎn)的引用LinkedList.Node<E> next = x.next;// 將當(dāng)前節(jié)點(diǎn) x 的元素值、前驅(qū)節(jié)點(diǎn)和后繼節(jié)點(diǎn)都設(shè)置為 null,從而切斷當(dāng)前節(jié)點(diǎn)與前后節(jié)點(diǎn)的關(guān)聯(lián)x.item = null;x.next = null;x.prev = null;// 將 x 更新為下一個(gè)節(jié)點(diǎn),以便進(jìn)行下一次循環(huán)迭代x = next;}// 清空頭節(jié)點(diǎn)和尾節(jié)點(diǎn)的引用,使整個(gè)鏈表為空first = last = null;// 將鏈表的大小設(shè)置為 0,表示鏈表中不再包含任何元素size = 0;// 更新修改次數(shù)計(jì)數(shù)器,用于在迭代過(guò)程中檢測(cè)并發(fā)修改modCount++;
}

3.8 indexOf()方法

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

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

4.1 LinkedList適用場(chǎng)景

LinkedList在Java中適用于以下場(chǎng)景

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

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

4.2 LinkedList與ArrayList的比較

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

LinkedList的特點(diǎn)

  • 基于雙向鏈表實(shí)現(xiàn),每個(gè)節(jié)點(diǎn)都包含指向前一個(gè)節(jié)點(diǎn)和后一個(gè)節(jié)點(diǎn)的引用。
  • 高效地支持插入和刪除操作,因?yàn)橹恍枰淖兦昂蠊?jié)點(diǎn)的指針指向即可。
  • 在使用迭代器進(jìn)行遍歷時(shí),效率較高。
  • 對(duì)于頻繁的插入和刪除操作,LinkedList通常比ArrayList更加高效。

ArrayList的特點(diǎn)

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

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

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

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

4.3 LinkedList的使用注意事項(xiàng)

在使用 Java 中的 LinkedList 時(shí),有一些需要注意的事項(xiàng),包括但不限于以下幾點(diǎn):

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

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

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

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

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

1.定義一個(gè)雙向鏈表和一個(gè)哈希表,用于存儲(chǔ)緩存數(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.實(shí)現(xiàn) get 方法,每次獲取數(shù)據(jù)時(shí),將數(shù)據(jù)移到鏈表頭部,并更新哈希表中的位置信息。

public Object get(String key) {CacheNode node = cacheMap.get(key);if (node == null) {return null;}// 將節(jié)點(diǎn)移動(dòng)到鏈表頭部moveToHead(node);return node.value;
}private void moveToHead(CacheNode node) {// 先將節(jié)點(diǎn)從原有位置刪除removeNode(node);// 將節(jié)點(diǎn)插入到鏈表頭部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.實(shí)現(xiàn) put 方法,每次存儲(chǔ)數(shù)據(jù)時(shí),如果緩存已滿,則淘汰鏈表尾部的數(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é)點(diǎn)到鏈表頭部,并添加位置信息到哈希表node = new CacheNode(key, value);cacheMap.put(key, node);insertNodeAtHead(node);if (cacheMap.size() > capacity) {// 如果緩存已滿,則淘汰鏈表尾部的節(jié)點(diǎn),并刪除相應(yīng)位置信息CacheNode removedNode = removeNodeAtTail();cacheMap.remove(removedNode.key);}}
}private CacheNode removeNodeAtTail() {CacheNode removedNode = tail.prev;removeNode(removedNode);return removedNode;
}

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

可以通過(guò)如下代碼進(jìn)行簡(jiǎn)單的測(cè)試

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://www.risenshineclean.com/news/44111.html

相關(guān)文章:

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