集合系列(一):集合框架概述

来源:https://www.cnblogs.com/chanshuyi/archive/2019/08/23/java_collection_01_summary.html
-Advertisement-
Play Games

集合系列(一):集合框架概述 Java 集合是 Java API 用得最頻繁的一類,掌握 Java 集合的原理以及繼承結構非常有必要。總的來說,Java 容器可以劃分為 4 個部分: List 集合 Set 集合 Queue 集合 Map 集合 除了上面 4 種集合之外,還有一個專門的工具類: 工具 ...


集合系列(一):集合框架概述

Java 集合是 Java API 用得最頻繁的一類,掌握 Java 集合的原理以及繼承結構非常有必要。總的來說,Java 容器可以劃分為 4 個部分:

  • List 集合
  • Set 集合
  • Queue 集合
  • Map 集合

除了上面 4 種集合之外,還有一個專門的工具類:

  • 工具類(Iterator 迭代器、Enumeration 枚舉類、Arrays 和 Collections)

在開始聊具體的集合體系之前,我想先介紹一下 Collection 框架的基本類結構。因為無論是 List 集合、Set 集合還是 Map 集合都以這個為基礎。

  • 首先,最頂層的是 Collection 介面。

可以看到 Collection 介面定義了最最基本的集合操作,例如:判斷集合大小、判斷集合是否為空等。List、Set、Queue 都繼承了該介面。

  • 接著,AbstractCollection 也繼承了 Collection 介面。

從這個類名可以看出,其是一個抽象類。AbstractCollection 對 Collection 介面中一些通用的方法做了實現。例如:判斷是否為空的方法、判斷是否包含某個元素的方法等。

通過繼承 AbstractCollection 介面,可以少寫許多不必要的代碼,這是代碼抽象設計最常用的思想。AbstractCollection 是最為基礎的類,其他所有集合的實現都繼承了這個抽象類。

List 集合

List 集合存儲的是有序的數據集合,其數據結構特點是:讀取快,修改慢,適合於讀取多、寫入修改少的場景。List 集合的類繼承結構如下:

我們可以看到除了 Collection 和 AbstractCollection 之外,我們還有 List 介面和 AbstractList 抽象類。其中 List 介面是 List 集合的最上層抽象,其繼承了 Collection 介面,表示其實一個集合。而 AbstractList 則是 List 集合的抽象實現,實現了許多公用的操作。

整個 List 集合的實現可以分為紅、黃、綠三大塊。其中紅色部分是 List 集合的列表實現,綠色部分是 List 結合的鏈表實現,而 黃色部分則是 List 集合列表實現的線程安全版本。

列表實現

ArrayList 類是很常用的 List 實現,其底層是用數組實現的。其讀取元素的時間複雜度是 O(1),修改寫入元素的時間複雜度是 O(N)。我們將會在下麵的章節中詳細介紹,這裡不做深入。

列表安全實現

Vector 類也是很常用的 List 實現,其數據結構與 ArrayList 非常類似。但其與 ArrayList 的一個最大的不同是:Vector 是線程安全的,而 ArrayList 則不是線程安全的。

Stack 類則是在 Vector 的基礎上,又實現了一個雙向隊列。所以其除了是線程安全的之外,其還是一個先進後出的 List 實現。

最後我們總結一下,List 集合最為關鍵的幾個實現類是:

  • ArrayList:列表集合經典實現。
  • Vector:列表集合經典實現,線程安全,與 ArrayList 對應。
  • Stack:棧結構的經典實現,先進後出的數據結構。繼承了 Vector,線程安全。
  • LinkedList:鏈表結構的經典實現。

鏈表實現

LinkedList 是一個經典的鏈表實現。LinkedList 繼承了 AbstractSequentialList 抽象類。AbstractSequentialList 抽象類從字面上理解是抽象連續列表。這裡的重點是
sequential 這個詞,表示其數據結構是連續的(鏈表)。從其源碼註釋也可以看出這個意思。

This class provides a skeletal implementation of the List interface to minimize the effort required to implement this interface backed by a "sequential access" data store (such as a linked list).
(意譯)如果你想要實現一個連續存儲(鏈表)的 List,那麼這個抽象類可以讓你減少不少工足量。

其實從命名就可以看出,AbstractSequentialList 其實是連續列表(鏈表)的一個抽象實現。AbstractSequentialList 抽象類做了許多工作,使得後續的鏈表實現更加簡單。從 AbstractSequentialList 的註釋可以看到,如果要實現一個鏈表,那麼只需要實現 listIterator 方法和 size 方法就可以了。

Set 集合

Set 集合中存儲的元素是不重覆的,但是其存儲順序是無序的。下麵是 Set 集合的類繼承結構圖:

與 List 集合類似,都是一個 Set 介面繼承了 Collection 介面。一個 AbstractSet 抽象類實現了 Set 介面、繼承了 AbstractCollection 抽象類。這部分完全和 List 相同。

Set 集合的實現可以分為兩大塊,一塊是 Set 集合的有序實現(紅色部分),另一塊是 Set 集合的哈希實現(黃色部分)。

有序實現(TreeSet)

  • SortedSet 介面繼承了 Set 介面,TreeSet 實現了 SortedSet。

我們知道 Set 集合中的元素是無序的,而 SortedSet 介面則是定義了有序 Set 集合的介面。而 TreeSet 則是 SortedSet 的具體實現。

哈希實現(HashSet、LinkedHashSet)

HashSet 是 Set 介面的經典哈希實現。但 Set 集合中的元素是無序的,為了維護 Set 集合的插入順序,人們創造出了 LinkedHashSet。LinkedHashSet 在 HashSet 的基礎上是用鏈表維護元素的插入順序。

到這裡我們總結一下 Set 集合的所有實現:

  • TreeSet:Set 集合的有序實現。
  • HashSet:Set 集合的哈希實現。
  • LinkedHashSet:Set 集合的哈希實現,維護了元素插入順序。

Queue 集合

隊列是一個特殊的線性表,其數據結構特點是先進先出。Queue 類結構體系如下圖所示:

首先,Queue 介面繼承了 Collection 介面。Queue 介面在擁有基本集合操作的基礎上,定義了隊列這種數據結構的基本操作。可以看到 offer、poll 等方法都是隊列獨有的操作。

接著,AbstractQueue 是對 Queue 介面的抽象實現。針對隊列這種數據結構,其添加、刪除元素的動作都不一樣。在 AbstractQueue 抽象類里將隊列的基本操作都實現了一遍。例如 AbstractQueue 中的 add 方法就和 AbstractList 中的 add 方法有著不同的實現。

如上圖所示,Queue 的類結構整體可以分為黃色、紅色兩個部分。紅色部分是 Queue 介面的有序實現,有 PriorityQueue 這個實現類。黃色部分是 Deque(雙向隊列)的實現,有 LinkedList 和 ArrayDeque 兩個實現類。

有序實現

PriorityQueue 是 AbstractQueue 抽象類的具體實現。

PriorityQueue 表示優先順序隊列,其按照隊列元素的大小進行重新排序。當調用 peek() 或 pool() 方法取出隊列中頭部的元素時,並不是取出最先進入隊列的元素,而是取出隊列的最小元素。

雙向實現

  • 首先,我們會看到 Deque 介面。

Deque(double ended queue)是雙向隊列的意思,它能在頭部或尾部進行元素操作。

  • 最後,我們看到 LinkedList 和 ArrayDeque 都是 Deque 介面的具體實現。

LinkedList 我們之前說過了,是一個鏈表,但它還是一個雙向隊列。因此 LinkedList 具有 List 和 Queue 的雙重特性。ArrayDeque 則是一個雙向迴圈隊列,其底層是用數組實現。更多內容,我們將在隊列章節講解。

最後我們總結 Queue 體系的幾個常見實現類:

  • PriorityQueue:優先順序隊列
  • LinkedList:雙向隊列實現
  • ArrayDeque:雙向迴圈隊列實現

Map 集合

Map 集合與 List、Set、Queue 有較大不同,其實類似於 key/value 的數據結構。

  • 首先,Map 介面是最頂層的介面。

與 List、Set、Queue 類似,Map 介面定義的是哈希表數據結構的操作。例如我們常用的 put、get、keySet 等。

  • 接著,有 AbstractMap 抽象類。

和 List 等類似,AbstractMap 是 Map 介面的抽象實現。如上圖所示,Map 集合的整個類結構可以分為紅、黃、綠三塊。

哈希實現

紅色部分可以看成是 Map 的哈希實現。

  • AbstractMap 有具體的實現類 HashMap。

HashMap 是 AbstractMap 基於哈希演算法的具體實現。

  • 接著,LinkedHashMap 和 WeakedHashMap 繼承了 HashMap。

LinkedHashMap 是 HashMap 的進一步實現,其用鏈表保存了插入 HashMap 中的元素順序。WeakedHashMap 是 HashMap 的進一步實現,與 HashMap不同的是:WeakedHashMap 中的引用是弱引用,如果太久沒用,則會被自動回收。

有序實現

黃色部分可以看成是 Map 集合的有序實現。

  • 首先,SortedMap 介面繼承了 Map 介面。

與 Set 一樣,Map 中的元素是沒有順序的,SortedMap 就是有序 Map 的介面定義。

  • 接著,NavigableMap 繼承了 SortedMap 介面。

NavigableMap 介面定義了一些查找邏輯,方便後續實現。

  • 最後,TreeMap 則是 NavigableMap 介面的具體實現。

其實 TreeMap 是基於紅黑樹的 Map 實現。

看到了這裡,Map 整個類結構看完了一半。而另外一半則是以 Dictionary 為主的實現(綠色部分)。但實際上 Dictionary 是老舊的 Map 實現,現在已經廢棄了。我們從源碼的註釋中可以看到相關的提示。

NOTE: This class is obsolete(廢棄的).  New implementations should implement the Map interface, rather than extending this class.
這個類已經被廢棄,新的實現應該實現 Map 介面,而不是擴展這個類。

所以針對於 Dictionary 的實現,我們並不打算深入講解。

到這裡我們總結一下 Map 集合的所有實現類:

  • HashMap:Map 集合的經典哈希實現。
  • LinkedHashMap:在 HashMap 的基礎上,增加了對插入元素的鏈表維護。
  • WeakedHashMap:在 HashMap 的基礎上,使強引用變為弱引用。
  • TreeMap:Map 集合的有序實現。

工具類

集合的工具類有:Iterator 迭代器、ListIterator 迭代器、Enumeration 枚舉類、Arrays 和 Collections 類。

Iterator 迭代器

Iterator 迭代器是一個用來遍歷並選擇序列中的對象。Java 的 Iterator 只能單向移動。可以看到在 ArrayList、WeakHashMap 等集合類都實現了該介面,從而實現不同類型集合的遍歷。

ListIterator 迭代器

ListIterator 繼承了 Iterator 介面,所以其有更強大的功能,即它能夠實現雙向移動。但從其名字也可以看出,其只能適用於 List 集合的遍歷。

Enumeration 枚舉類

它是 JDK 1.0引入的介面。作用和Iterator一樣,也是遍歷集合。但是Enumeration的功能要比Iterator少。Enumeration只能在Hashtable, Vector, Stack中使用。這種傳統介面已被迭代器取代,雖然 Enumeration 還未被遺棄,但在代碼中已經被很少使用了。

官方也在文檔中推薦使用 Iterator 介面來替代 Enumeration 介面。

Arrays

Java.util.Arrays類能方便地操作數組,它提供的所有方法都是靜態的。

Collections

java.util.Collections 是一個包含各種有關集合操作的靜態多態方法的工具類,服務於 Java 的 Collection 框架。

總結

我們花費了大量的篇幅講解了 List 集合、Set 集合、Map 集合、Queue 集合以及 Iterator 等工具類。我們對這集合的類結構進行了詳細的解析,從而更加瞭解他們之間的關係。

有時候我們會想,瞭解這麼多有啥用呢。我有個朋友只用了常見的 ArrayList、HashMap 就可以了啊。對於這個問題,我想分享幾個收穫。

第一,讓你更加熟悉類之間的差異。 如果我們只會用一兩個類,那麼我們就不知道在什麼時候用什麼類。例如:什麼時候用 HashMap,什麼時候用 Hashtable?Iterator 介面有什麼作用?JDK源碼的命名有什麼特點?

第二,方便對源碼進行擴展。 當我們深入研究了集合的實現之後,我們知道了原來 List 介面就是 List 這種數據類型的定義,而 AbstractList 是 List 的抽象實現。那麼如果我們要實現一個自定義的 List 結構,那麼我們就可以直接繼承 AbstractList 類,從而達到快速實現的目的。但如果你沒有深入研究呢?你或許只能從頭寫起,這樣得浪費多大的精力啊。你學會了這種方式,那麼對於你擴展 Spring 源碼也是有很好的幫助的。

在接下來的文章里,我們將深入介紹每一個集合的具體實現。


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

-Advertisement-
Play Games
更多相關文章
  • jQuery是一個Javascript庫,它支持鏈式操作方式,即對發生在同一個JQuery對象上的一組動作,可以直接接連寫無需要重覆獲取對象。這一特點使得JQuery的代碼無比優雅,而且有強大的選擇器,出色的DOM操作,可靠的事件處理機制,完善的Ajax,關鍵是有出色的瀏覽器相容性,開發項目時可以不 ...
  • 1. ...
  • 這次分享我們就來談談單例模式的使用,其實在本公眾號設計模式的第一篇分享就是單例模式,為什麼又要討論單例模式了?主要是那篇文章談的比較淺,只對單例模式的主要思想做了一個分享,這篇文章會從多個方面去分享單例模式的使用,下麵進入正題。 使用Java做程式的小伙伴都知道單例,尤其是使用spring框架做項目 ...
  • 本文將介紹微服務架構和相關的組件,介紹他們是什麼以及為什麼要使用微服務架構和這些組件。本文側重於簡明地表達微服務架構的全局圖景,因此不會涉及具體如何使用組件等細節。 為了防止不提供原網址的轉載,特在這裡加上原文鏈接: "https://www.cnblogs.com/skabyy/p/1139657 ...
  • 代碼參考:https://github.com/HCJ shadow/Zuul Gateway Cluster Nginx Zuul的路由轉發功能 前期準備 搭建Eureka服務註冊中心 服務提供者msc provider 5001【提供一個hello請求做測試】 創建gateway 7001 p ...
  • 一、複習 1.標識符(自己定義的,下劃線、美元符號) 2.駝峰命名(變數名,方法名首字母小寫) 3.關鍵字(就是固定的那幾個) 4.字面值(數據、有類型、八種基本類型從小到大,byte\char=short\int\long\float\double\boolean 5.成員變數(初始化在方法外且不 ...
  • 23:59 2019/8/23 成員變數: 對象的成員變數,或者普通成員變數; 類的成員變數,或者靜態成員變數 下麵是source code和.class->.java(反編譯後)的source code ...
  • 功能需求:在前端頁面中,for迴圈id會構不成連續的順序號,所以要找到一種偽列的方式來根據數據量定義序號 因此就用到了在前端頁面中的一個欄位 forloop.counter,完美解決 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:本文代碼示例演示瞭如何在WPF中使用LiveCharts庫創建動態條形圖。通過創建數據模型、ViewModel和在XAML中使用`CartesianChart`控制項,你可以輕鬆實現圖表的數據綁定和動態更新。我將通過清晰的步驟指南包括詳細的中文註釋,幫助你快速理解並應用這一功能。 先上效果: 在 ...
  • openGauss(GaussDB ) openGauss是一款全面友好開放,攜手伙伴共同打造的企業級開源關係型資料庫。openGauss採用木蘭寬鬆許可證v2發行,提供面向多核架構的極致性能、全鏈路的業務、數據安全、基於AI的調優和高效運維的能力。openGauss深度融合華為在資料庫領域多年的研 ...
  • openGauss(GaussDB ) openGauss是一款全面友好開放,攜手伙伴共同打造的企業級開源關係型資料庫。openGauss採用木蘭寬鬆許可證v2發行,提供面向多核架構的極致性能、全鏈路的業務、數據安全、基於AI的調優和高效運維的能力。openGauss深度融合華為在資料庫領域多年的研 ...
  • 概述:本示例演示了在WPF應用程式中實現多語言支持的詳細步驟。通過資源字典和數據綁定,以及使用語言管理器類,應用程式能夠在運行時動態切換語言。這種方法使得多語言支持更加靈活,便於維護,同時提供清晰的代碼結構。 在WPF中實現多語言的一種常見方法是使用資源字典和數據綁定。以下是一個詳細的步驟和示例源代 ...
  • 描述(做一個簡單的記錄): 事件(event)的本質是一個委托;(聲明一個事件: public event TestDelegate eventTest;) 委托(delegate)可以理解為一個符合某種簽名的方法類型;比如:TestDelegate委托的返回數據類型為string,參數為 int和 ...
  • 1、AOT適合場景 Aot適合工具類型的項目使用,優點禁止反編 ,第一次啟動快,業務型項目或者反射多的項目不適合用AOT AOT更新記錄: 實實在在經過實踐的AOT ORM 5.1.4.117 +支持AOT 5.1.4.123 +支持CodeFirst和非同步方法 5.1.4.129-preview1 ...
  • 總說周知,UWP 是運行在沙盒裡面的,所有許可權都有嚴格限制,和沙盒外交互也需要特殊的通道,所以從根本杜絕了 UWP 毒瘤的存在。但是實際上 UWP 只是一個應用模型,本身是沒有什麼許可權管理的,許可權管理全靠 App Container 沙盒控制,如果我們脫離了這個沙盒,UWP 就會放飛自我了。那麼有沒... ...
  • 目錄條款17:讓介面容易被正確使用,不易被誤用(Make interfaces easy to use correctly and hard to use incorrectly)限制類型和值規定能做和不能做的事提供行為一致的介面條款19:設計class猶如設計type(Treat class de ...
  • title: 從零開始:Django項目的創建與配置指南 date: 2024/5/2 18:29:33 updated: 2024/5/2 18:29:33 categories: 後端開發 tags: Django WebDev Python ORM Security Deployment Op ...
  • 1、BOM對象 BOM:Broswer object model,即瀏覽器提供我們開發者在javascript用於操作瀏覽器的對象。 1.1、window對象 視窗方法 // BOM Browser object model 瀏覽器對象模型 // js中最大的一個對象.整個瀏覽器視窗出現的所有東西都 ...