Java中集合List、Set和Map的入門詳細(xì)介紹
一、Collection接口
1.1 是集合框架的頂級(jí)接口
1.2 是Set和List的父接口
1.3 但不是Map的父接口

二、List集合
2.1介紹
Java的List是非常常用的數(shù)據(jù)類型。List是有序的Collection。Java List一共三個(gè)實(shí)現(xiàn)類:
2.1.1 ArrayList(數(shù)組)
ArrayList 是最常用的 List 實(shí)現(xiàn)類,內(nèi)部是通過數(shù)組實(shí)現(xiàn)的,它允許對(duì)元素進(jìn)行快速隨機(jī)訪問。數(shù)組的缺點(diǎn)是每個(gè)元素之間不能有間隔,當(dāng)數(shù)組大小不滿足時(shí)需要增加存儲(chǔ)能力,就要將已經(jīng)有數(shù)組的數(shù)據(jù)復(fù)制到新的存儲(chǔ)空間中(動(dòng)態(tài)擴(kuò)容)。當(dāng)從 ArrayList 的中間位置插入或者刪除元素時(shí),需要對(duì)數(shù)組進(jìn) 行復(fù)制、移動(dòng)、代價(jià)比較高。因此,它適合隨機(jī)查找和遍歷,不適合插入和刪除。

2.1.2 Vector(數(shù)組實(shí)現(xiàn)、線程同步)
Vector 與 ArrayList 一樣,也是通過數(shù)組實(shí)現(xiàn)的,不同的是它支持線程的同步,即某一時(shí)刻只有一 個(gè)線程能夠?qū)?Vector,避免多線程同時(shí)寫而引起的不一致性,但實(shí)現(xiàn)同步需要很高的花費(fèi),因此, 訪問它比訪問 ArrayList 慢。
2.1.3 LinkList(鏈表)
LinkedList 是用鏈表結(jié)構(gòu)存儲(chǔ)數(shù)據(jù)的,很適合數(shù)據(jù)的動(dòng)態(tài)插入和刪除,隨機(jī)訪問和遍歷速度比較慢。另外,他還提供了 List 接口中沒有定義的方法,專門用于操作表頭和表尾元素,可以當(dāng)作堆棧、隊(duì)列和雙向隊(duì)列使用。

2.2 List特性
- 可以存放同一種類型的元素。
- 內(nèi)部維護(hù)元素之間的順序,是有序集合。
- 元素是可以重復(fù)的。
2.3 List常用方法
A:添加功能 boolean add(E e):向集合中添加一個(gè)元素 void add(int index, E element):在指定位置添加元素 boolean addAll(Collection<? extends E> c):向集合中添加一個(gè)集合的元素。 B:刪除功能 void clear():刪除集合中的所有元素 E remove(int index):根據(jù)指定索引刪除元素,并把刪除的元素返回 boolean remove(Object o):從集合中刪除指定的元素 boolean removeAll(Collection<?> c):從集合中刪除一個(gè)指定的集合元素。 C:修改功能 E set(int index, E element):把指定索引位置的元素修改為指定的值,返回修改前的值。 D:獲取功能 E get(int index):獲取指定位置的元素 Iterator iterator():就是用來獲取集合中每一個(gè)元素。 E:判斷功能 boolean isEmpty():判斷集合是否為空。 boolean contains(Object o):判斷集合中是否存在指定的元素。 boolean containsAll(Collection<?> c):判斷集合中是否存在指定的一個(gè)集合中的元素。 F:長(zhǎng)度功能 int size():獲取集合中的元素個(gè)數(shù) G:把集合轉(zhuǎn)換成數(shù)組 Object[] toArray():把集合變成數(shù)組。
2.4 List總結(jié)
2.4.1內(nèi)部存儲(chǔ)結(jié)構(gòu)區(qū)別:
- ArrayList、Vector是數(shù)組存儲(chǔ)。LinkedList是**鏈表存儲(chǔ) (不支持下標(biāo)遍歷)。
2.4.2 線程安全區(qū)別:
- ArrayList、LinkedList是線程不安全。Vector是線程安全(但是Vector已過時(shí),雖然它線程安全,但導(dǎo)致增刪改查都慢,屬于犧牲性能,提高安全性)。
三、Set集合
3.1介紹
Set 注重獨(dú)一無二的性質(zhì),該體系集合用于存儲(chǔ)無序(存入和取出的順序不一定相同)元素,值不能重復(fù)。對(duì)象的相等性本質(zhì)是對(duì)象 hashCode 值(java 是依據(jù)對(duì)象的內(nèi)存地址計(jì)算出的此序號(hào))判斷的
3.2 分類
3.2.1 HashSet(Hash表)
哈希表邊存放的是哈希值。HashSet 存儲(chǔ)元素的順序并不是按照存入時(shí)的順序(和 List 顯然不同) 而是按照哈希值來存的所以取數(shù)據(jù)也是按照哈希值取得。
總結(jié):元素的哈希值是通過元素的hashcode方法 來獲取的, HashSet首先判斷兩個(gè)元素的哈希值,如果哈希值一樣,接著會(huì)比較equals方法 如果 equls結(jié)果為true ,HashSet就視為同一個(gè)元素。如果equals 為false就不是同一個(gè)元素。
哈希值相同equals為false的元素是怎么存儲(chǔ)呢,就是在同樣的哈希值下順延(可以認(rèn)為哈希值相同的元素放在一個(gè)哈希桶中)。也就是哈希一樣的存一列。
3.2.2 TreeSet(二叉樹)
- TreeSet()是使用二叉樹的原理對(duì)新 add()的對(duì)象按照指定的順序排序(升序、降序),每增加一個(gè)對(duì)象都會(huì)進(jìn)行排序,將對(duì)象插入的二叉樹指定的位置。
- Integer 和 String 對(duì)象都可以進(jìn)行默認(rèn)的 TreeSet 排序,而自定義類的對(duì)象是不可以的,自己定義的類必須實(shí)現(xiàn) Comparable 接口,并且覆寫相應(yīng)的 compareTo()函數(shù),才可以正常使用。
- 在覆寫 compare()函數(shù)時(shí),要返回相應(yīng)的值才能使 TreeSet 按照一定的規(guī)則來排序
- 比較此對(duì)象與指定對(duì)象的順序。如果該對(duì)象小于、等于或大于指定對(duì)象,則分別返回負(fù)整數(shù)、零或正整數(shù)。
3.2.3 LinkHashSet(HashSet+LinkedHashMap)
對(duì)于 LinkedHashSet 而言,它繼承與 HashSet、又基于 LinkedHashMap 來實(shí)現(xiàn)的。 LinkedHashSet 底層使用 LinkedHashMap 來保存所有元素,它繼承與 HashSet,其所有的方法 操作上又與 HashSet 相同,因此 LinkedHashSet 的實(shí)現(xiàn)上非常簡(jiǎn)單,只提供了四個(gè)構(gòu)造方法,并通過傳遞一個(gè)標(biāo)識(shí)參數(shù),調(diào)用父類的構(gòu)造器,底層構(gòu)造一個(gè) LinkedHashMap 來實(shí)現(xiàn),在相關(guān)操作上與父類 HashSet 的操作相同,直接調(diào)用父類 HashSet 的方法即可。
四、Map集合
4.1 HashMap(數(shù)組+鏈表+紅黑樹)
HashMap 根據(jù)鍵的 hashCode 值存儲(chǔ)數(shù)據(jù),大多數(shù)情況下可以直接定位到它的值,因而具有很快的訪問速度,但遍歷順序卻是不確定的。 HashMap 最多只允許一條記錄的鍵為 null,允許多條記 錄的值為 null。HashMap 非線程安全,即任一時(shí)刻可以有多個(gè)線程同時(shí)寫 HashMap,可能會(huì)導(dǎo)致數(shù)據(jù)的不一致。如果需要滿足線程安全,可以用 Collections 的 synchronizedMap 方法使 HashMap 具有線程安全的能力,或者使用 ConcurrentHashMap。我們用下面這張圖來介紹HashMap 的結(jié)構(gòu)。


4.2 ConcurrentHashMap

4.2.1 Segment段
ConcurrentHashMap 和 HashMap 思路是差不多的,但是因?yàn)樗С植l(fā)操作,所以要復(fù)雜一 些。整個(gè) ConcurrentHashMap 由一個(gè)個(gè) Segment 組成,Segment 代表”部分“或”一段“的意思,所以很多地方都會(huì)將其描述為分段鎖。注意,行文中,我很多地方用了“槽”來代表一個(gè)segment。
4.2.2 線程安全(Segment 繼承ReentrantLock 加鎖)
簡(jiǎn)單理解就是,ConcurrentHashMap 是一個(gè) Segment 數(shù)組,Segment 通過繼承 ReentrantLock 來進(jìn)行加鎖,所以每次需要加鎖的操作鎖住的是一個(gè) segment,這樣只要保證每個(gè) Segment 是線程安全的,也就實(shí)現(xiàn)了全局的線程安全。
4.2.3 并行度(默認(rèn)16)
concurrencyLevel:并行級(jí)別、并發(fā)數(shù)、Segment 數(shù),怎么翻譯不重要,理解它。默認(rèn)是 16, 也就是說 ConcurrentHashMap 有 16 個(gè) Segments,所以理論上,這個(gè)時(shí)候,最多可以同時(shí)支 持 16 個(gè)線程并發(fā)寫,只要它們的操作分別分布在不同的 Segment 上。這個(gè)值可以在初始化的時(shí)候設(shè)置為其他值,但是一旦初始化以后,它是不可以擴(kuò)容的。再具體到每個(gè) Segment 內(nèi)部,其實(shí)每個(gè) Segment 很像之前介紹的 HashMap,不過它要保證線程安全,所以處理起來要麻煩些。
4.2.4 Java8實(shí)現(xiàn) (引入了紅黑樹)
Java8 對(duì) ConcurrentHashMap 進(jìn)行了比較大的改動(dòng),Java8 也引入了紅黑樹。

4.3 HashTable(線程安全)
Hashtable 是遺留類,很多映射的常用功能與 HashMap 類似,不同的是它承自 Dictionary 類,并且是線程安全的,任一時(shí)間只有一個(gè)線程能寫 Hashtable,并發(fā)性不如 ConcurrentHashMap,因?yàn)?ConcurrentHashMap 引入了分段鎖。Hashtable 不建議在新代碼中使用,不需要線程安全的場(chǎng)合可以用 HashMap 替換,需要線程安全的場(chǎng)合可以用 ConcurrentHashMap 替換。
4.4 TreeMap(可排序)
TreeMap 實(shí)現(xiàn) SortedMap 接口,能夠把它保存的記錄根據(jù)鍵排序,默認(rèn)是按鍵值的升序排序, 也可以指定排序的比較器,當(dāng)用 Iterator 遍歷 TreeMap 時(shí),得到的記錄是排過序的。如果使用排序的映射,建議使用 TreeMap。 在使用 TreeMap 時(shí),key 必須實(shí)現(xiàn) Comparable 接口或者在構(gòu)造 TreeMap 傳入自定義的 Comparator,否則會(huì)在運(yùn)行時(shí)拋出 java.lang.ClassCastException 類型的異常。
參考:https://blog.csdn.net/chenssy/article/details/26668941
4.5 LinkHashMap(記錄插入順序)
LinkedHashMap 是 HashMap 的一個(gè)子類,保存了記錄的插入順序,在用 Iterator 遍歷LinkedHashMap 時(shí),先得到的記錄肯定是先插入的,也可以在構(gòu)造時(shí)帶參數(shù),按照訪問次序排序。
參考 :https://blog.csdn.net/qq_40050586/article/details/105851970
總結(jié)
到此這篇關(guān)于Java中集合List、Set和Map的文章就介紹到這了,更多相關(guān)Java集合List、Set和Map內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java集合框架之Set和Map詳解
- Java?集合框架掌握?Map?和?Set?的使用(內(nèi)含哈希表源碼解讀及面試??碱})
- Java多線程高并發(fā)中解決ArrayList與HashSet和HashMap不安全的方案
- 深入解讀Java三大集合之map list set的用法
- JAVA中的 map,list,set
- java中Map、Set、List的簡(jiǎn)單使用教程(快速入門)
- Java HashSet(散列集),HashMap(散列映射)的簡(jiǎn)單介紹
- java的各種集合為什么不安全(List、Set、Map)以及代替方案
- Java數(shù)據(jù)結(jié)構(gòu)之Map與Set專篇講解
相關(guān)文章
SpringBoot + Spring Security 基本使用及個(gè)性化登錄配置詳解
這篇文章主要介紹了SpringBoot + Spring Security 基本使用及個(gè)性化登錄配置詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-05-05
詳解Java接口簽名(Signature)實(shí)現(xiàn)方案
這篇文章主要介紹了Java接口簽名(Signature)實(shí)現(xiàn)方案?,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-01-01
feign name指定服務(wù)調(diào)用無效問題及解決
文章主要介紹了FeignClient注解的常用屬性,并通過一個(gè)具體的例子說明了為什么某個(gè)Feign調(diào)用需要使用url指定路徑才能訪問,最后,文章給出了解決辦法,即使用path屬性指定前綴2024-11-11
SpringCloud OpenFeign 參數(shù)傳遞和響應(yīng)處理的詳細(xì)步驟
本文給大家講解SpringCloud OpenFeign 參數(shù)傳遞和響應(yīng)處理的詳細(xì)步驟,本文給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2024-02-02
關(guān)于Java錯(cuò)誤提示之找不到或無法加載主類的問題及正確處理方法
當(dāng)我們?cè)诔鯇W(xué)Java的是時(shí)候,類文件中是不設(shè)定包名(package)的,這種情況下注意classpath,基本上沒有問題,?本文主要說明classpath和系統(tǒng)環(huán)境變量PATH都沒問題的情況下出錯(cuò)原因和正確處理方法,感興趣的朋友一起看看吧2022-01-01

