LinkedList源碼刨析

来源:https://www.cnblogs.com/angelMask/archive/2022/07/14/16470024.html
-Advertisement-
Play Games

數組和結點這兩種數據結構之間的差異,決定了LinkedList相比ArrayList擁有更高的插入和刪除效率,而隨機訪問效率不如ArrayList。 transient transient只能用來修飾成員變數(field),被transient修飾的成員變數不參與序列化過程。 序列化: JVM中的J ...


數組和結點這兩種數據結構之間的差異,決定了LinkedList相比ArrayList擁有更高的插入和刪除效率,而隨機訪問效率不如ArrayList。


目錄

transient

transient只能用來修飾成員變數(field),被transient修飾的成員變數不參與序列化過程。

序列化: JVM中的Java對象轉化為位元組序列。

反序列化: 位元組序列轉化為JVM中的Java對象。

靜態成員變數即使不加transient關鍵字也無法被序列化。

Externalizable

自定義序列化,無視transient關鍵字

public class Person implements Externalizable {
    private String nickName;
    private transient String realName;
    
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeUTF(realName);
        out.writeUTF(childName);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        realName = in.readUTF();
        childName = in.readUTF();
    }
    
    public static void main(String[] args){
        //序列化
        os = new ObjectOutputStream(new FileOutputStream(filePath));
        os.writeObject(x);
        //反序列化
        is = new ObjectInputStream(new FileInputStream(filePath));
        Person readObject = (Person)is.readObject();
    }
}

LinkedList源碼刨析

Node

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

因為存在數據結構基礎,不全記錄,只記錄覺得寫的妙的源碼和比較經典的源碼。

看了一段就知道,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;
    
    //因為類中只記錄了first結點和last結點,通過一次二分可以找到目標結點和first結點比較接近還是last結點比較接近
	Node<E> node(int 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;
        }
	}
    
    //如果原頭結點為空,則讓尾指針指向新結點(頭尾重合);如果原頭結點不為空,那麼就讓原頭結點的前指針指向新的頭結點
    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;
        else
            f.prev = newNode;
        size++;
        modCount++;
    }
    
    //將原尾節點的後指針指向新的尾節點
    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++;
    }
    
    //插入到succ結點之前
    void linkBefore(E e, Node<E> succ) {
        //記錄succ的前指針
        final Node<E> pred = succ.prev;
        //pred<-newNode->succ
        final Node<E> newNode = new Node<>(pred, e, succ);
        //將prev<-succ修改為newNode<-succ
        succ.prev = newNode;
        if (pred == null)
            //前指針為空,說明succ為頭指針,而現在newNode為頭指針
            first = newNode;
        else
            //將pred->succ 修改為 pred->newNode
            pred.next = newNode;
        size++;
        modCount++;
    }
    
    //這也有棧頂?peek出的first頭節點。
    public E peek() {
        final Node<E> f = first;
        return (f == null) ? null : f.item;
    }
    
    //很粗暴的轉換數組
    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;
    }
    
    
}


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 苦惱於Python運行時感人的速度,我決定學習C++。 為了激勵我自己好好地學習這門未曾謀面的編程語言,我決定在此開設專欄:C++學習日記。希望在讀者們的監督下,我可以早日掌握這門語言。當然,如果那位大佬願意賜教,在下也是感激不盡。 2022年7月14日 由於懶得安裝編譯環境,我找了一個線上編程的網 ...
  • 面向對象編程(基礎) 類與對象 ●使用現有技術解決 張老太養了兩隻貓貓:一隻名字叫小白,今年3歲,白色。還有一隻叫小花,今年100歲,花色。請編寫一個程式,當用戶輸入小貓的名字時,就顯示該貓的名字,年齡,顏色。如果用戶輸入的小貓名錯誤,則顯示張老太沒有這隻貓貓。 1)單獨的定義變數解決 2)使用數組 ...
  • MyDisruptor V5版本介紹 在v4版本的MyDisruptor實現多線程生產者後。按照計劃,v5版本的MyDisruptor需要支持更便於用戶使用的DSL風格的API。 由於該文屬於系列博客的一部分,需要先對之前的博客內容有所瞭解才能更好地理解本篇博客 v1版本博客:從零開始實現lmax- ...
  • 為了在命令行程式中實現和用戶的交互,我們編寫的程式的運行過程中往往涉及到對標準輸入/輸出流的多次讀寫。 在C語言中接受用戶輸入這一塊,有著一個老生常談的問題:“怎麼樣及時清空輸入流中的數據?” 這也是這篇小筆記的主題內容。 先從緩衝區說起。 緩衝區是記憶體中劃分出來的一部分。通常來說,緩衝區類型有三種 ...
  • day23今日內容概要: 1.絕對導入與相對導入 2.包的概念(package) 3.模塊化編程思想簡介 4.軟體開發目錄規範 5.常見內置函數:collections和time 6.作業(將員工管理系統用模塊化編程,結合軟體開發目錄規範來封裝) 今日內容詳解 1.絕對導入和相對導入 PS:只要存在 ...
  • 預設參數的坑 定義一個函數,傳入一個list,添加一個end再返回 def add_end(L=[]): L.append('END') return L 正常調用時,結果似乎不錯 print (add_end([1,2,3])) #[1, 2, 3, 'END'] 使用預設參數調用時,一開始結果也 ...
  • 作為JAVA開發中最典型的異常類型,甚至可能是很多程式員入行之後收到的第一份異常大禮包類型,NullPointException也似乎成為了一種魔咒,應該如何去打破呢?一起來探討下吧 ...
  • 總結:Java的Stack嚴格意義來說並不能說是Stack,因為它通過直接繼承Vector類,繼承了Vector所有的公有方法,它是一個擁有所有Vector容器方法的棧! @SuppressWarnings 該批註的作用是給編譯器一條指令,告訴它對被批註的代碼元素內部的某些警告保持靜默。 | all ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...