開發場景中Java 集合的最佳選擇

在 Java 開發中,集合類是處理數據的核心工具。合理選擇集合,不僅可以提高代碼效率,還能讓代碼更簡潔。本篇文章將重點探討 List、SetMap?的適用場景及優缺點,幫助你在實際開發中找到最佳解決方案。

一、List:有序存儲的/最佳選擇

1. ArrayList:快速查詢與動態數組

應用場景:當你需要頻繁查詢元素,或者存儲的元素數目動態變化時,ArrayList 是首選。例如:分頁展示用戶數據。

代碼示例:

List<String> users = new ArrayList<>();
users.add("Alice");
users.add("Bob");
System.out.println(users.get(1)); // 輸出 Bob

底層結構ArrayList 使用一個 動態數組 來存儲元素。初始時,數組的大小是固定的,當元素超過數組的容量時,會自動擴展數組的大小。

優點

  • 查詢效率高:數組支持按索引快速訪問元素,時間復雜度為 O(1),因此 get() 操作非常高效。

  • 內存局部性:數組存儲在連續的內存空間中,CPU 緩存友好,可以利用 CPU 的緩存機制提高訪問效率。

缺點

  • 插入和刪除效率低:當插入或刪除元素時,尤其是在中間位置時,必須移動數組中的大量元素,時間復雜度為 O(n)

  • 擴容操作代價高:數組擴容時需要分配新的數組并將舊數組元素復制到新數組,操作的時間復雜度為 O(n)


2. LinkedList:高效增刪的雙向鏈表

應用場景:需要頻繁在列表中間或首尾插入、刪除數據時,例如實現任務隊列。

代碼示例:

LinkedList<String> tasks = new LinkedList<>();
tasks.addFirst("Task1");
tasks.addLast("Task2");
tasks.removeFirst();

底層結構LinkedList 使用 雙向鏈表,每個元素都有兩個指針:一個指向前一個元素,一個指向下一個元素。這樣可以在常數時間內插入或刪除元素。

優點

  • 插入和刪除高效:無論是在鏈表的頭部、中部還是尾部,插入和刪除元素的時間復雜度都為 O(1),因為只需要改變相關節點的指針。

  • 內存使用靈活:每個元素的內存可以分散存儲,不需要連續的內存塊。

【比如在中間插入

假設需要在鏈表中的某個位置 node 前插入新節點 newNode

  1. newNodenext 指向 node,將 newNodeprev 指向 node.prev

  2. 更新 node.prev.nextnewNode,更新 node.prevnewNode

這只涉及 4 次指針操作,與鏈表的長度無關,因此在已定位到目標節點后,插入操作的時間復雜度為 O(1)

缺點

  • 查詢效率低:為了查找元素,必須從頭節點或尾節點開始遍歷鏈表,時間復雜度為 O(n)

  • 內存開銷大:每個元素都需要額外存儲指向前后元素的指針,相較于數組,占用更多的內存。


二、Set:無重復集合的首選

1. HashSet:高效去重

應用場景:當需要存儲一組不允許重復的元素,且對順序沒有要求時,例如用戶注冊時驗證用戶名的唯一性。

代碼示例

Set<String> usernames = new HashSet<>();
usernames.add("Alice");
usernames.add("Bob");
usernames.add("Alice"); // 重復的元素會被忽略
System.out.println(usernames.size()); // 輸出 2

底層結構HashSet 使用 哈希表HashMap)【哈希表在文末有補充講解】來存儲元素。哈希表通過將元素的哈希碼映射到表中的桶來進行存儲,確保元素是唯一的。

優點

  • 去重高效:哈希表能夠快速判斷元素是否已存在,因為它通過哈希值進行查找,時間復雜度為 O(1)

  • 查詢效率高:哈希表的查找時間復雜度為 O(1),因此 contains()add() 操作非常高效。

缺點

  • 無序存儲:哈希表并不維護元素的順序,因此 HashSet 中的元素是無序的。

  • 哈希沖突:不同的元素可能具有相同的哈希值,哈希沖突會影響性能,但通常情況下,哈希表的設計會盡量減少沖突的概率。


2. LinkedHashSet:有序去重

應用場景:當需要去重的同時保留插入順序,例如記錄用戶最近瀏覽的商品。

代碼示例:

Set<String> products = new LinkedHashSet<>();
products.add("Laptop");
products.add("Phone");
products.add("Laptop"); // 再次添加無效
System.out.println(products); // 輸出 [Laptop, Phone]

底層結構LinkedHashSet 使用一個 哈希表 來存儲元素,并通過一個 雙向鏈表 來維護元素的插入順序。

優點

  • 有序存儲:由于鏈表的存在,LinkedHashSet 能夠保持元素的插入順序,訪問時能夠按照插入的順序遍歷元素。

  • 去重高效:與 HashSet 一樣,哈希表提供了快速的查找和去重機制。

缺點性能略低于 HashSet,由于還需要維護鏈表,LinkedHashSet 的操作稍微比 HashSet 慢,但差距通常不大。


3. TreeSet:排序與去重兼備

應用場景:當需要去重的同時對元素進行排序,例如實現排行榜或數據字典。

代碼示例:

TreeSet<Integer> scores = new TreeSet<>();
scores.add(50);
scores.add(80);
scores.add(70);
System.out.println(scores); // 輸出 [50, 70, 80]

底層結構TreeSet 使用 紅黑樹 來存儲元素。紅黑樹是一種自平衡的二叉搜索樹,能夠確保樹的深度保持在對數級別。

優點

  • 有序存儲TreeSet 會自動對元素進行排序,默認按自然順序排序compareTo(Object obj))或者通過傳入 Comparator 自定義排序)。

  • 查找、插入和刪除的時間復雜度為 O(log n):由于紅黑樹的結構特性,所有操作的時間復雜度為對數級別。

缺點性能較低,相比哈希表,紅黑樹的插入、刪除和查找操作的時間復雜度為 O(log n),因此在大量數據操作時,性能略遜色于 HashSetLinkedHashSet

三、Map:鍵值對存儲的首選

Map 是存儲鍵值對的集合類,每個鍵唯一對應一個值。常用于快速查找和關聯關系的存儲。

1. HashMap:高效的鍵值映射

應用場景:需要高效查找時,例如存儲用戶 ID 和用戶信息的映射。

代碼示例:

Map<Integer, String> userMap = new HashMap<>();
userMap.put(1, "Alice");
userMap.put(2, "Bob");
System.out.println(userMap.get(1)); // 輸出 Alice

底層結構HashMap 使用 哈希表 來存儲鍵值對,通過鍵的哈希碼來確定存儲位置。

優點

  • 查找和插入高效:查找、插入和刪除操作的時間復雜度為 O(1),通過哈希值直接定位位置。

  • 支持鍵值對的存儲:每個鍵對應唯一的值,適合各種映射操作。

缺點

  • 無序存儲:哈希表中的元素是無序的,因此遍歷時無法保證順序。


2. LinkedHashMap:有序的鍵值映射

應用場景:需要既保持插入順序,又能高效查找,例如實現最近訪問頁面的緩存。

代碼示例:

Map<Integer, String> accessLog = new LinkedHashMap<>();
accessLog.put(1, "HomePage");
accessLog.put(2, "ProfilePage");
accessLog.put(3, "SettingsPage");
System.out.println(accessLog); // 輸出 {1=HomePage, 2=ProfilePage, 3=SettingsPage}

底層結構LinkedHashMap 使用 哈希表 存儲元素,并通過 雙向鏈表 維護元素的插入順序。

優點

  • 有序存儲:保持了元素的插入順序,遍歷時能夠按照插入順序輸出。

  • 高效查找:與 HashMap 一樣,查詢和插入操作的時間復雜度為 O(1)

缺點內存開銷較大,需要額外的內存來存儲鏈表指針。


3. TreeMap:有序的鍵值存儲

應用場景:需要按鍵排序存儲鍵值對,例如實現字典或排行榜。

代碼示例:

Map<Integer, String> sortedMap = new TreeMap<>();
sortedMap.put(3, "C");
sortedMap.put(1, "A");
sortedMap.put(2, "B");
System.out.println(sortedMap); // 輸出 {1=A, 2=B, 3=C}
  • 底層結構TreeMap 使用 紅黑樹 來存儲鍵值對,按照鍵的自然順序(或通過指定的 Comparator)進行排序。

  • 優點

    • 有序存儲:自動對鍵進行排序,適用于需要順序訪問鍵值對的場景。

    • 高效的查找、插入和刪除:操作時間復雜度為 O(log n)

  • 缺點性能略低于 HashMapLinkedHashMap,由于紅黑樹需要維護平衡,操作的時間復雜度為對數級別,性能不如哈希表

4. Properties

應用場景

  • Properties 常用于管理應用程序的配置信息,如數據庫連接信息、語言國際化資源等。

  • 它可以方便地加載和存儲鍵值對到 .properties 文件中,支持流式操作。

代碼示例:

import java.io.*;
import java.util.Properties;
?
public class PropertiesExample {public static void main(String[] args) throws IOException {Properties properties = new Properties();// 設置鍵值對properties.setProperty("database.url", "jdbc:mysql://localhost:3306/mydb");properties.setProperty("database.user", "root");properties.setProperty("database.password", "password");
?// 保存到文件try (FileOutputStream output = new FileOutputStream("config.properties")) {properties.store(output, "Database Configuration");}
?// 從文件加載try (FileInputStream input = new FileInputStream("config.properties")) {properties.load(input);}
?// 打印所有屬性properties.forEach((key, value) -> System.out.println(key + ": " + value));}
}

底層結構

  • Properties 的基礎是 Hashtable

    • 底層采用線程安全的哈希表結構。

    • 鍵和值均為字符串類型(String),以適應配置文件的存儲和解析需求。

    • 提供了 load()store() 方法,用于流式操作,方便配置文件的讀寫。

優點

  1. 簡單直觀:內置方法支持直接操作配置文件,減少手動解析的復雜性;適合存儲和管理小規模配置。

  2. 線程安全:繼承自 Hashtable,所有操作均是同步的,適合簡單的多線程環境。

  3. 與文件系統集成良好:提供了流式操作接口,方便將鍵值對直接保存為 .properties 文件或從文件中加載。

缺點

  1. 性能較低:由于繼承自同步的 Hashtable,在現代高并發場景下不推薦使用,性能落后于 HashMap

  2. 局限性:僅支持 String 類型的鍵值對,若需要存儲復雜對象,需額外序列化。

  3. 不適合大規模配置:適合小型項目或簡單模塊的配置管理,大型系統建議采用更復雜的配置管理工具(如 Apache Commons Configuration 或 Spring)。

總結

集合類底層數據結構主要優點主要缺點
ArrayList動態數組查詢效率高,支持隨機訪問插入刪除效率低,擴容代價大
LinkedList雙向鏈表插入刪除效率高,內存靈活查詢效率低,占用內存大
HashSet哈希表查詢和去重效率高無序存儲,受哈希沖突影響
LinkedHashSet哈希表 + 雙向鏈表有序存儲,去重效率高內存占用較高
TreeSet紅黑樹有序存儲,按自然順序或自定義順序排序性能略低于哈希表,操作復雜度為 O(log n)
HashMap哈希表查找和插入效率高,支持鍵值對映射無序存儲,受哈希沖突影響
LinkedHashMap哈希表 + 雙向鏈表有序存儲,按插入順序遍歷鍵值對內存開銷較高
TreeMap紅黑樹有序存儲,按鍵自然順序或自定義順序排序性能略低于哈希表,操作復雜度為 O(log n)
Properties哈希表(繼承自 Hashtable專為存儲鍵值對配置設計,支持讀寫 .properties 文件性能較低(繼承自同步的 Hashtable),不適合高并發

知識點補充

1. 什么是哈希表?

哈希表是一種用來存儲 鍵值對 的工具,它能非常快速地找到數據。你可以把它想象成一個 帶編號的儲物柜,每個柜子都有一個編號(索引),你把東西存進去時,會根據物品的特點計算出一個編號,然后直接放進對應的柜子里。取東西時也用相同的方法計算編號,直接找到對應的柜子打開拿走。

例子

  • 假如你有一本字典,查找某個單詞(鍵)對應的解釋(值)。

  • 傳統查找方法:逐頁翻閱,耗時長。

  • 使用哈希表:計算單詞的編號,直接跳到對應的位置查看解釋,速度非常快。

總結類比

  • 鍵是 “單詞”,值是 “解釋”。

  • 哈希表通過哈希函數快速找到這個單詞在哪頁。


2. 哈希表是如何存數據的?

哈希表的核心在于 哈希函數。這個函數就像一個計算器,可以把一個鍵(比如一個字符串)變成一個數字(哈希值)。哈希值用來確定數據存儲的位置。

步驟:

  1. 計算位置:用哈希函數把鍵變成一個數字,然后對儲物柜的總數取模(%),確定放在哪個柜子里。假如儲物柜有 10 個,"Alice" 的哈希值是 42,42 % 10 = 2,所以數據放到第 2 個柜子。

  2. 存儲值:把數據放到計算出的柜子里。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/64427.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/64427.shtml
英文地址,請注明出處:http://en.pswp.cn/web/64427.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java包裝類型的緩存

Java 基本數據類型的包裝類型的大部分都用到了緩存機制來提升性能。 Byte,Short,Integer,Long 這 4 種包裝類默認創建了數值 [-128&#xff0c;127] 的相應類型的緩存數據&#xff0c;Character 創建了數值在 [0,127] 范圍的緩存數據&#xff0c;Boolean 直接返回 True or Fal…

工程師 - MinGW

MinGW Minimalist GNU for Windows&#xff0c;前身為mingw32&#xff0c;是一個免費開源的軟件開發環境&#xff0c;從2010年開始項目停止并不再使用。后續提供MinGW-w64。 MinGW包括: - 移植到Windows上的GNU編譯器集&#xff08;GCC&#xff09;&#xff0c;包括C、C、ADA和…

EasyExcel(讀取操作和填充操作)

文章目錄 1.準備Read.xlsx&#xff08;具有兩個sheet&#xff09;2.讀取第一個sheet中的數據1.模板2.方法3.結果 3.讀取所有sheet中的數據1.模板2.方法3.結果 EasyExcel填充1.簡單填充1.準備 Fill01.xlsx2.無模版3.方法4.結果 2.列表填充1.準備 Fill02.xlsx2.模板3.方法4.結果 …

CKA認證 | Day7 K8s存儲

第七章 Kubernetes存儲 1、數據卷與數據持久卷 為什么需要數據卷&#xff1f; 容器中的文件在磁盤上是臨時存放的&#xff0c;這給容器中運行比較重要的應用程序帶來一些問題。 問題1&#xff1a;當容器升級或者崩潰時&#xff0c;kubelet會重建容器&#xff0c;容器內文件會…

Python調用R語言中的程序包來執行回歸樹、隨機森林、條件推斷樹和條件推斷森林算法

要使用Python調用R語言中的程序包來執行回歸樹、隨機森林、條件推斷樹和條件推斷森林算法&#xff0c;重新計算中國居民收入不平等&#xff0c;并進行分類匯總&#xff0c;我們可以使用rpy2庫。rpy2允許在Python中嵌入R代碼并調用R函數。以下是一個詳細的步驟和示例代碼&#x…

關于JAVA方法值傳遞問題

1.1 前言 之前在學習C語言的時候&#xff0c;將實參傳遞給方法&#xff08;或函數&#xff09;的方式分為兩種&#xff1a;值傳遞和引用傳遞&#xff0c;但在JAVA中只有值傳遞&#xff08;顛覆認知&#xff0c;基礎沒學踏實&#xff09; 參考文章&#xff1a;https://blog.csd…

Excel基礎知識

一&#xff1a;數組 一行或者一列數據稱為一維數組&#xff0c;多行多列稱為二維數組&#xff0c;數組支持算術運算&#xff08;如加減乘除等&#xff09;。 行&#xff1a;{1,2,3,4} 數組中的每個值用逗號分隔列&#xff1a;{1;2;3;4} 數組中的每個值用分號分隔行列&#xf…

基于DIODES AP43781+PI3USB31531+PI3DPX1207C的USB-C PD Video 之全功能顯示器連接端口方案

隨著USB-C連接器和PD功能的出現&#xff0c;新一代USB-C PD PC顯示器可以用作個人和專業PC工作環境的電源和數據集線器。 雖然USB-C PD顯示器是唯一插入墻壁插座的交流電源輸入設備&#xff0c;但它可以作為數據UFP&#xff08;上游接口&#xff09;連接到連接到TCD&#xff0…

gazebo_world 基本圍墻。

如何使用&#xff1f; 參考gazebo harmonic的官方教程。 本人使用harmonic的template&#xff0c;在里面進行修改就可以分流暢地使用下去。 以下是world 文件. <?xml version"1.0" ?> <!--Try sending commands:gz topic -t "/model/diff_drive/…

解決無法在 Ubuntu 24.04 上運行 AppImage 應用

在 Ubuntu 24.04 中運行 AppImage 應用的完整指南 在 Ubuntu 24.04 中&#xff0c;許多用戶可能會遇到 AppImage 應用無法啟動的問題。即使你已經設置了正確的文件權限&#xff0c;AppImage 仍然拒絕運行。這通常是由于缺少必要的庫文件所致。 問題根源&#xff1a;缺少 FUSE…

Pytorch使用手冊-DCGAN 指南(專題十四)

1. Introduction 本教程將通過一個示例介紹 DCGANs(深度卷積生成對抗網絡)。我們將訓練一個生成對抗網絡(GAN),在給它展示大量真實名人照片后,它能夠生成新的“名人”圖片。這里的大部分代碼來源于 PyTorch 官方示例中的 DCGAN 實現,而本文檔將對該實現進行詳細解釋,并…

springboot配置oracle+達夢數據庫多數據源配置并動態切換

項目場景&#xff1a; 在工作中很多情況需要跨數據庫進行數據操作,自己總結的經驗希望對各位有所幫助 問題描述 總結了幾個問題 1.識別不到mapper 2.識別不到xml 3.找不到數據源 原因分析&#xff1a; 1.配置文件編寫導致識別mapper 2.配置類編寫建的格式有問題 3.命名…

html+css+js網頁設計 美食 家美食1個頁面

htmlcssjs網頁設計 美食 家美食1個頁面 網頁作品代碼簡單&#xff0c;可使用任意HTML輯軟件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html編輯軟件進行運行及修改編輯等操作&#xff09;。 獲取源碼 1&#xf…

【機器學習】【樸素貝葉斯分類器】從理論到實踐:樸素貝葉斯分類器在垃圾短信過濾中的應用

&#x1f31f; 關于我 &#x1f31f; 大家好呀&#xff01;&#x1f44b; 我是一名大三在讀學生&#xff0c;目前對人工智能領域充滿了濃厚的興趣&#xff0c;尤其是機器學習、深度學習和自然語言處理這些酷炫的技術&#xff01;&#x1f916;&#x1f4bb; 平時我喜歡動手做實…

Vue使用Tinymce 編輯器

目錄 一、下載并重新組織tinymce結構二、使用三、遇到的坑 一、下載并重新組織tinymce結構 下載 npm install tinymce^7 or yarn add tinymce^7重構目錄 在node_moudles里找到tinymce文件夾&#xff0c;把里面文件拷貝一份放到public下&#xff0c;如下&#xff1a; -- pub…

odoo中@api.model, @api.depends和@api.onchange 裝飾器的區別

文章目錄 1. api.model用途特點示例 2. api.depends用途特點示例 3. api.onchange用途特點示例 總結 在 Odoo 中&#xff0c;裝飾器&#xff08;decorators&#xff09;用于修飾方法&#xff0c;以指定它們的行為和觸發條件。api.model、api.depends 和 api.onchange 是三個常用…

EMNLP'24 最佳論文解讀 | 大語言模型的預訓練數據檢測:基于散度的校準方法

點擊藍字 關注我們 AI TIME歡迎每一位AI愛好者的加入&#xff01; 點擊 閱讀原文 觀看作者講解回放&#xff01; 作者簡介 張偉超&#xff0c;中國科學院計算所網絡數據科學與技術重點實驗室三年級直博生 內容簡介 近年來&#xff0c;大語言模型&#xff08;LLMs&#xff09;的…

大數據技術-Hadoop(一)Hadoop集群的安裝與配置

目錄 一、準備工作 1、安裝jdk&#xff08;每個節點都執行&#xff09; 2、修改主機配置 &#xff08;每個節點都執行&#xff09; 3、配置ssh無密登錄 &#xff08;每個節點都執行&#xff09; 二、安裝Hadoop&#xff08;每個節點都執行&#xff09; 三、集群啟動配置&a…

PilotGo

title: 解鎖 PilotGo&#xff1a;智能化運維的得力助手 date: ‘2024-12-29’ category: blog tags: PilotGo運維管理智能化工具技術應用 sig: ops archives: ‘2024-12’ author:way_back summary: PilotGo 作為一款創新的運維管理工具&#xff0c;憑借其智能化的特性和豐富的…

折騰日記:如何讓吃灰筆記本發揮余熱——搭建一個相冊服務

背景 之前寫過&#xff0c;我在家里用了一臺舊的工作站筆記本做了服務器&#xff0c;連上一個綠聯的5位硬盤盒實現簡單的網盤功能&#xff0c;然而&#xff0c;還是覺的不太理想&#xff0c;比如使用filebrowser雖然可以備份文件和圖片&#xff0c;當使用手機使用網頁&#xf…