日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java 集合容器篇面试题(上)-王者笔记《收藏版》

發(fā)布時間:2025/3/12 java 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 集合容器篇面试题(上)-王者笔记《收藏版》 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前期推薦閱讀:

Java基礎(chǔ)知識學(xué)習(xí)總結(jié)(上)

Java 基礎(chǔ)知識學(xué)習(xí)總結(jié)(下)

大學(xué)生一個暑假學(xué)會5個神仙賺錢技能 | 你學(xué)會了幾個?

畢設(shè)/私活/大佬必備,一個掙錢的開源前后端分離腳手架

目錄

一、集合容器概述

1.1 什么是集合

1.2 集合的特點(diǎn)

1.3 集合和數(shù)組的區(qū)別? ?

1.4 使用集合框架的好處

1.5 常用的集合類有哪些?

1.6 List,Set,Map三者的區(qū)別和特點(diǎn)?

1.7 集合框架底層數(shù)據(jù)結(jié)構(gòu)

1. List

2. Set

3.Map

1.8 哪些集合類是線程安全的?

1.9 Java集合的快速失敗機(jī)制 “fail-fast”?

1.10 怎么確保一個集合不能被修改?

二 、Collection接口

2.1 List接口

2.1.1迭代器 Iterator 是什么?

2.1.2 Iterator 怎么使用?有什么特點(diǎn)?

2.1.3 如何邊遍歷邊移除 Collection 中的元素?

2.1.4 Iterator 和 ListIterator 有什么區(qū)別?

2.1.5 遍歷一個 List 有哪些不同的方式?每種方法的實(shí)現(xiàn)原理是什么?Java中 List 遍歷的最佳實(shí)踐是什么?

2.1.6 說一下 ArrayList 的優(yōu)缺點(diǎn)

2.1.7 如何實(shí)現(xiàn)數(shù)組和 List 之間的轉(zhuǎn)換?

2.1.8 ArrayList 和 LinkedList 的區(qū)別是什么?

2.1.9 ArrayList 和 Vector 的區(qū)別是什么?

2.1.10 插入數(shù)據(jù)時,ArrayList、LinkedList、Vector誰速度較快?闡述ArrayList、Vector、LinkedList 的存儲性能和特性?

2.1.11 多線程場景下如何使用 ArrayList?

2.1.12 為什么 ArrayList 的 elementData 加上 transient 修飾?

2.1.13 List 和 Set 的區(qū)別

2.2 Set接口

2.2.1 說一下 HashSet 的實(shí)現(xiàn)原理?

2.2.2 HashSet如何檢查重復(fù)?HashSet是如何保證數(shù)據(jù)不可重復(fù)的?

2.2.3 HashSet與HashMap的區(qū)別

2.3 Queue

2.3.1BlockingQueue是什么?

下一期:介紹 Java 集合容器篇面試題(下)

Java項(xiàng)目實(shí)戰(zhàn)分享:


一、集合容器概述

1.1 什么是集合

集合框架:用于存儲數(shù)據(jù)的容器。??

集合框架是為表示和操作集合而規(guī)定的一種統(tǒng)一的標(biāo)準(zhǔn)的體系結(jié)構(gòu)。

任何集合框架都包含三大塊內(nèi)容:對外的接口、接口的實(shí)現(xiàn)和對集合運(yùn)算的算法。

接口:表示集合的抽象數(shù)據(jù)類型。接口允許我們操作集合時不必關(guān)注具體實(shí)現(xiàn),從而達(dá)到“多態(tài)”。在面向?qū)ο缶幊陶Z言中,接口通常用來形成規(guī)范。

實(shí)現(xiàn):集合接口的具體實(shí)現(xiàn),是重用性很高的數(shù)據(jù)結(jié)構(gòu)。

算法:在一個實(shí)現(xiàn)了某個集合框架中的接口的對象身上完成某種有用的計(jì)算的方法,例如查找、排序等。這些算法通常是多態(tài)的,因?yàn)橄嗤姆椒梢栽谕粋€接口被多個類實(shí)現(xiàn)

時有不同的表現(xiàn)。事實(shí)上,算法是可復(fù)用的函數(shù)。

它減少了程序設(shè)計(jì)的辛勞。

集合框架通過提供有用的數(shù)據(jù)結(jié)構(gòu)和算法使你能集中注意力于你的程序的重要部分上,而不是為了讓程序能正常運(yùn)轉(zhuǎn)而將注意力于低層設(shè)計(jì)上。

通過這些在無關(guān)API之間的簡易的互用性,使你免除了為改編對象或轉(zhuǎn)換代碼以便聯(lián)合這些API而去寫大量的代碼。 它提高了程序速度和質(zhì)量。?

1.2 集合的特點(diǎn)

集合的特點(diǎn)主要有如下兩點(diǎn):

? ? 對象封裝數(shù)據(jù),對象多了也需要存儲。集合用于存儲對象。

? ? 對象的個數(shù)確定可以使用數(shù)組,對象的個數(shù)不確定的可以用集合。因?yàn)榧鲜强勺冮L度的。

1.3 集合和數(shù)組的區(qū)別? ?

? ? ?數(shù)組是固定長度的;集合可變長度的。

? ? ?數(shù)組可以存儲基本數(shù)據(jù)類型,也可以存儲引用數(shù)據(jù)類型;集合只能存儲引用數(shù)據(jù)類型。

? ? ?數(shù)組存儲的元素必須是同一個數(shù)據(jù)類型;集合存儲的對象可以是不同數(shù)據(jù)類型。

?數(shù)據(jù)結(jié)構(gòu):就是容器中存儲數(shù)據(jù)的方式。對于集合容器,有很多種。因?yàn)槊恳粋€容器的自身特點(diǎn)不同,其實(shí)原理在于每個容器的內(nèi)部數(shù)據(jù)結(jié)構(gòu)不同。

集合容器在不斷向上抽取過程中,出現(xiàn)了集合體系。在使用一個體系的原則:參閱頂層內(nèi)容。建立底層對象。

1.4 使用集合框架的好處

? ?1. 容量自增長;

? ?2. 提供了高性能的數(shù)據(jù)結(jié)構(gòu)和算法,使編碼更輕松,提高了程序速度和質(zhì)量;

? 3. 允許不同 API 之間的互操作,API之間可以來回傳遞集合;

? 4. 可以方便地?cái)U(kuò)展或改寫集合,提高代碼復(fù)用性和可操作性。

? 5. 通過使用JDK自帶的集合類,可以降低代碼維護(hù)和學(xué)習(xí)新API成本。

1.5 常用的集合類有哪些?

? Map接口和Collection接口是所有集合框架的父接口:

? ? 1. Collection接口的子接口包括:Set接口和List接口

? ? 2. Map接口的實(shí)現(xiàn)類主要有:HashMap、TreeMap、Hashtable、ConcurrentHashMap以及Properties等

? ? 3. Set接口的實(shí)現(xiàn)類主要有:HashSet、TreeSet、LinkedHashSet等

? ? 4. List接口的實(shí)現(xiàn)類主要有:ArrayList、LinkedList、Stack以及Vector等

1.6 List,Set,Map三者的區(qū)別和特點(diǎn)?

? ? ? ? ? ? ? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Collection結(jié)構(gòu)圖

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? map結(jié)構(gòu)圖

三種子接口。我們比較常用的是Set、List,Map接口不是collection的子接口。

Collection集合主要有List和Set兩大接口

? ? ? List:一個有序(元素存入集合的順序和取出的順序一致)容器,元素可以重復(fù),可以插入多個null元素,元素都有索引。常用的實(shí)現(xiàn)類有 ArrayList、LinkedList 和 Vector。

? ? ? Set:一個無序(存入和取出順序有可能不一致)容器,不可以存儲重復(fù)元素,只允許存入一個null元素,必須保證元素唯一性。Set 接口常用實(shí)現(xiàn)類是 HashSet、LinkedHashSet 以及TreeSet。

Map是一個鍵值對集合,存儲鍵、值和之間的映射。 Key無序,唯一;value 不要求有序,允許重復(fù)。Map沒有繼承于Collection接口,從Map集合中檢索元素時,只要給出鍵對象,就會返回對應(yīng)的值對象。

Map 的常用實(shí)現(xiàn)類:HashMap、TreeMap、HashTable、LinkedHashMap、ConcurrentHashMap

1.7 集合框架底層數(shù)據(jù)結(jié)構(gòu)

Collection

1. List

? ? Arraylist: Object數(shù)組

? ? Vector: Object數(shù)組

? ? LinkedList: 雙向循環(huán)鏈表

2. Set

? ? HashSet(無序,唯一):基于 HashMap 實(shí)現(xiàn)的,底層采用 HashMap 來保存元素

? ?LinkedHashSet: LinkedHashSet 繼承與 HashSet,并且其內(nèi)部是通過 LinkedHashMap來實(shí)現(xiàn)的。有點(diǎn)類似于我們之前說的LinkedHashMap 其內(nèi)部是基于 Hashmap 實(shí)現(xiàn)一樣,不過還是有一點(diǎn)點(diǎn)區(qū)別的。

? ?TreeSet(有序,唯一): 紅黑樹(自平衡的排序二叉樹。)

3.Map

? ? HashMap: JDK1.8之前HashMap由數(shù)組+鏈表組成的,數(shù)組是HashMap的主體,鏈表則是主要為了解決哈希沖突而存在的(“拉鏈法”解決沖突).JDK1.8以后在解決哈希沖突時有了較大的變化,當(dāng)鏈表長度大于閾值(默認(rèn)為8)時,將鏈表轉(zhuǎn)化為紅黑樹,以減少搜索時間

? ?LinkedHashMap:LinkedHashMap 繼承自 HashMap,所以它的底層仍然是基于拉鏈?zhǔn)缴⒘薪Y(jié)構(gòu)即由數(shù)組和鏈表或紅黑樹組成。另外,LinkedHashMap 在上面結(jié)構(gòu)的基礎(chǔ)上,增加了一條雙向鏈表,使得上面的結(jié)構(gòu)可以保持鍵值對的插入順序。同時通過對鏈表進(jìn)行相應(yīng)的操作,實(shí)現(xiàn)了訪問順序相關(guān)邏輯。

? HashTable: 數(shù)組+鏈表組成的,數(shù)組是 HashMap 的主體,鏈表則是主要為了解決哈希沖突而存在的

? TreeMap: 紅黑樹(自平衡的排序二叉樹)

1.8 哪些集合類是線程安全的?

? ?vector:就比arraylist多了個同步化機(jī)制(線程安全),因?yàn)樾瘦^低,現(xiàn)在已經(jīng)不太建議使用。在web應(yīng)用中,特別是前臺頁面,往往效率(頁面響應(yīng)速度)是優(yōu)先考慮的。

? statck:堆棧類,先進(jìn)后出。

? hashtable:就比hashmap多了個線程安全。

? enumeration:枚舉,相當(dāng)于迭代器。

1.9 Java集合的快速失敗機(jī)制 “fail-fast”?

?是java集合的一種錯誤檢測機(jī)制,當(dāng)多個線程對集合進(jìn)行結(jié)構(gòu)上的改變的操作時,有可能會產(chǎn)生 fail-fast 機(jī)制。

例如:假設(shè)存在兩個線程(線程1、線程2),線程1通過Iterator在遍歷集合A中的元素,

在某個時候線程2修改了集合A的結(jié)構(gòu)(是結(jié)構(gòu)上面的修改,而不是簡單的修改集合元素的內(nèi)容),那么這個時候程序就會拋出 ConcurrentModificationException 異常,從而產(chǎn)生fail-fast機(jī)制。

原因:迭代器在遍歷時直接訪問集合中的內(nèi)容,并且在遍歷過程中使用一個 modCount變量。集合在被遍歷期間如果內(nèi)容發(fā)生變化,就會改變modCount的值。每當(dāng)?shù)魇褂胔ashNext()/next()遍歷下一個元素之前,都會檢測modCount變量是否為expectedmodCount值,是的話就返回遍歷;否則拋出異常,終止遍歷。

解決辦法:

1. 在遍歷過程中,所有涉及到改變modCount值得地方全部加上synchronized。

2. 使用CopyOnWriteArrayList來替換ArrayList

1.10 怎么確保一個集合不能被修改?

可以使用Collections. unmodifiableCollection(Collection c) 方法來創(chuàng)建一個只讀集合,這樣改變集合的任何操作都會拋出 Java. lang. UnsupportedOperationException 異常。

示例代碼如下:

List list = new ArrayList<>();list. add("x");Collection clist = Collections.unmodifiableCollection(list);clist. add("y"); // 運(yùn)行時此行報錯System. out. println(list. size());

二 、Collection接口

2.1 List接口

2.1.1迭代器 Iterator 是什么?

Iterator 接口提供遍歷任何 Collection 的接口。我們可以從一個 Collection 中使用迭代器方法來獲取迭代器實(shí)例。迭代器取代了 Java 集合框架中的 Enumeration,迭代器允許調(diào)用者在迭代過程中移除元素。

2.1.2 Iterator 怎么使用?有什么特點(diǎn)?

Iterator 使用代碼如下:

public static void main(String[] args) throws IOException {List list = new ArrayList<>();Iterator it = list.iterator();while (it.hasNext()) {String obj = (String) it.next();System.out.println(obj);}}

Iterator 的特點(diǎn)是只能單向遍歷,但是更加安全,因?yàn)樗梢源_保,在當(dāng)前遍歷的集合元素被更改的時候,就會拋出 ConcurrentModificationException 異常。

2.1.3 如何邊遍歷邊移除 Collection 中的元素?

邊遍歷邊修改 Collection 的唯一正確方式是使用 Iterator.remove() 方法

一種最常見的錯誤代碼如下:

for(Integer i : list){ list.remove(i) }

運(yùn)行以上錯誤代碼會報 ConcurrentModificationException 異常。這是因?yàn)楫?dāng)使用foreach(for(Integer i : list)) 語句時,會自動生成一個iterator 來遍歷該 list,但同時該list 正在被 Iterator.remove() 修改。Java 一般不允許一個線程在遍歷 Collection 時另一個線程修改它。

2.1.4 Iterator 和 ListIterator 有什么區(qū)別?

? Iterator 可以遍歷 Set 和 List 集合,而 ListIterator 只能遍歷 List。

? Iterator 只能單向遍歷,而 ListIterator 可以雙向遍歷(向前/后遍歷)。

? ListIterator 實(shí)現(xiàn) Iterator 接口,然后添加了一些額外的功能,比如添加一個元素、替換一個元素、獲取前面或后面元素的索引位置。

2.1.5 遍歷一個 List 有哪些不同的方式?每種方法的實(shí)現(xiàn)原理是什么?Java中 List 遍歷的最佳實(shí)踐是什么?

遍歷方式有以下幾種:

? 1. for 循環(huán)遍歷,基于計(jì)數(shù)器。在集合外部維護(hù)一個計(jì)數(shù)器,然后依次讀取每一個位置的元素,當(dāng)讀取到最后一個元素后停止。

? 2. 迭代器遍歷,Iterator。Iterator 是面向?qū)ο蟮囊粋€設(shè)計(jì)模式,目的是屏蔽不同數(shù)據(jù)集合的特點(diǎn),統(tǒng)一遍歷集合的接口。Java 在 Collections 中支持了 Iterator 模式。

?3. foreach 循環(huán)遍歷。foreach 內(nèi)部也是采用了 Iterator 的方式實(shí)現(xiàn),使用時不需要顯式聲明 Iterator 或計(jì)數(shù)器。優(yōu)點(diǎn)是代碼簡潔,不易出錯;缺點(diǎn)是只能做簡單的遍歷,不能在遍歷過程中操作數(shù)據(jù)集合,例如刪除、替換。

最佳實(shí)踐:Java Collections 框架中提供了一個 RandomAccess 接口,用來標(biāo)記 List 實(shí)現(xiàn)是否支持 Random Access。

如果一個數(shù)據(jù)集合實(shí)現(xiàn)了該接口,就意味著它支持 Random Access,按位置讀取元素的平均時間復(fù)雜度為 O(1),如ArrayList。

如果沒有實(shí)現(xiàn)該接口,表示不支持 Random Access,如LinkedList。

推薦的做法就是,支持 Random Access 的列表可用 for 循環(huán)遍歷,否則建議用 Iterator或 foreach 遍歷。

2.1.6 說一下 ArrayList 的優(yōu)缺點(diǎn)

?ArrayList的優(yōu)點(diǎn)如下:

ArrayList 底層以數(shù)組實(shí)現(xiàn),是一種隨機(jī)訪問模式。ArrayList 實(shí)現(xiàn)了 RandomAccess 接口,因此查找的時候非常快。

ArrayList 在順序添加一個元素的時候非常方便。

ArrayList 的缺點(diǎn)如下:

刪除元素的時候,需要做一次元素復(fù)制操作。如果要復(fù)制的元素很多,那么就會比較耗費(fèi)性能。

插入元素的時候,也需要做一次元素復(fù)制操作,缺點(diǎn)同上。

ArrayList 比較適合順序添加、隨機(jī)訪問的場景。

2.1.7 如何實(shí)現(xiàn)數(shù)組和 List 之間的轉(zhuǎn)換?

數(shù)組轉(zhuǎn) List:使用 Arrays. asList(array) 進(jìn)行轉(zhuǎn)換。

List 轉(zhuǎn)數(shù)組:使用 List 自帶的 toArray() 方法。

代碼示例:

String[] strs = new String[] {"aaa", "bbb", "ccc"};List<String> list = Arrays.asList(strs);for (String s : list) {System.out.println(s);}

2.1.8 ArrayList 和 LinkedList 的區(qū)別是什么?

數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn):ArrayList 是動態(tài)數(shù)組的數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn),而 LinkedList 是雙向鏈表的數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)。

隨機(jī)訪問效率:ArrayList 比 LinkedList 在隨機(jī)訪問的時候效率要高,因?yàn)?LinkedList 是線性的數(shù)據(jù)存儲方式,所以需要移動指針從前往后依次查找。

增加和刪除效率:在非首尾的增加和刪除操作,LinkedList 要比 ArrayList 效率要高,因?yàn)锳rrayList 增刪操作要影響數(shù)組內(nèi)的其他數(shù)據(jù)的下標(biāo)。

內(nèi)存空間占用:LinkedList 比 ArrayList 更占內(nèi)存,因?yàn)?LinkedList 的節(jié)點(diǎn)除了存儲數(shù)據(jù),

還存儲了兩個引用,一個指向前一個元素,一個指向后一個元素。

線程安全:ArrayList 和 LinkedList 都是不同步的,也就是不保證線程安全;

綜合來說,在需要頻繁讀取集合中的元素時,更推薦使用 ArrayList,而在插入和刪除操作較多時,更推薦使用 LinkedList。

補(bǔ)充:數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)之雙向鏈表雙向鏈表也叫雙鏈表,是鏈表的一種,它的每個數(shù)據(jù)結(jié)點(diǎn)中都有兩個指針,分別指向直接

后繼和直接前驅(qū)。所以,從雙向鏈表中的任意一個結(jié)點(diǎn)開始,都可以很方便地訪問它的前驅(qū)結(jié)點(diǎn)和后繼結(jié)點(diǎn)。

2.1.9 ArrayList 和 Vector 的區(qū)別是什么?

這兩個類都實(shí)現(xiàn)了 List 接口(List 接口繼承了 Collection 接口),他們都是有序集合

線程安全:Vector 使用了 Synchronized 來實(shí)現(xiàn)線程同步,是線程安全的,而 ArrayList 是非線程安全的。

性能:ArrayList 在性能方面要優(yōu)于 Vector。

擴(kuò)容:ArrayList 和 Vector 都會根據(jù)實(shí)際的需要動態(tài)的調(diào)整容量,只不過在 Vector 擴(kuò)容每次會增加 1 倍,而 ArrayList 只會增加 50%。

Vector類的所有方法都是同步的。可以由兩個線程安全地訪問一個Vector對象、但是一個線程訪問Vector的話代碼要在同步操作上耗費(fèi)大量的時間。

Arraylist不是同步的,所以在不需要保證線程安全時時建議使用Arraylist。

2.1.10 插入數(shù)據(jù)時,ArrayList、LinkedList、Vector誰速度較快?闡述ArrayList、Vector、LinkedList 的存儲性能和特性?

ArrayList、LinkedList、Vector 底層的實(shí)現(xiàn)都是使用數(shù)組方式存儲數(shù)據(jù)。數(shù)組元素?cái)?shù)大于實(shí)際存儲的數(shù)據(jù)以便增加和插入元素,它們都允許直接按序號索引元素,但是插入元素要涉及數(shù)組元素移動等內(nèi)存操作,所以索引數(shù)據(jù)快而插入數(shù)據(jù)慢。

Vector 中的方法由于加了 synchronized 修飾,因此 Vector是線程安全容器,但性能上較ArrayList差。

LinkedList 使用雙向鏈表實(shí)現(xiàn)存儲,按序號索引數(shù)據(jù)需要進(jìn)行前向或后向遍歷,但插入數(shù)據(jù)時只需要記錄當(dāng)前項(xiàng)的前后項(xiàng)即可,所以 LinkedList插入速度較快。

2.1.11 多線程場景下如何使用 ArrayList?

ArrayList 不是線程安全的,如果遇到多線程場景,可以通過 Collections 的

synchronizedList 方法將其轉(zhuǎn)換成線程安全的容器后再使用。例如像下面這樣:

List <String>list=new ArrayList<String>();List<String> synchronizedList = Collections.synchronizedList(list);synchronizedList.add("aaa");synchronizedList.add("bbb");for (int i = 0; i < synchronizedList.size(); i++) {System.out.println(synchronizedList.get(i));}

2.1.12 為什么 ArrayList 的 elementData 加上 transient 修飾?

ArrayList 中的數(shù)組定義如下:

private transient Object[] elementData;

再看一下 ArrayList 的定義:

public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable{}

可以看到 ArrayList 實(shí)現(xiàn)了 Serializable 接口,這意味著 ArrayList 支持序列化。

transient 的作用是說不希望 elementData 數(shù)組被序列化,重寫了 writeObject 實(shí)現(xiàn):

private void writeObject(java.io.ObjectOutputStream s){try {s.writeObject(name);s.writeObject(age);System.out.println("重寫了writeObject");} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}

每次序列化時,先調(diào)用 default WriteObject() 方法序列化 ArrayList 中的非 transient 元素,然后遍歷 elementData,只序列化已存入的元素,這樣既加快了序列化的速度,又減小了序列化之后的文件大小。

2.1.13 List 和 Set 的區(qū)別

List , Set 都是繼承自Collection 接口

List 特點(diǎn):一個有序(元素存入集合的順序和取出的順序一致)容器,元素可以重復(fù),可以插入多個null元素,元素都有索引。常用的實(shí)現(xiàn)類有 ArrayList、LinkedList 和Vector。

Set 特點(diǎn):一個無序(存入和取出順序有可能不一致)容器,不可以存儲重復(fù)元素,只允許存入一個null元素,必須保證元素唯一性。Set 接口常用實(shí)現(xiàn)類是 HashSet、

LinkedHashSet 以及 TreeSet。

另外 List 支持for循環(huán),也就是通過下標(biāo)來遍歷,也可以用迭代器,但是set只能用迭代,

因?yàn)樗麩o序,無法用下標(biāo)來取得想要的值。

Set和List對比

Set:檢索元素效率低下,刪除和插入效率高,插入和刪除不會引起元素位置改變。

List:和數(shù)組類似,List可以動態(tài)增長,查找元素效率高,插入刪除元素效率低,因?yàn)闀鹌渌匚恢酶淖?/p>

2.2 Set接口

2.2.1 說一下 HashSet 的實(shí)現(xiàn)原理?

HashSet 是基于 HashMap 實(shí)現(xiàn)的,HashSet的值存放于HashMap的key上,HashMap的value統(tǒng)一為PRESENT,因此 HashSet 的實(shí)現(xiàn)比較簡單,相關(guān) HashSet 的操作,基本上都是直接調(diào)用底層 HashMap 的相關(guān)方法來完成,HashSet 不允許重復(fù)的值。

2.2.2 HashSet如何檢查重復(fù)?HashSet是如何保證數(shù)據(jù)不可重復(fù)的?

向HashSet 中add ()元素時,判斷元素是否存在的依據(jù),不僅要比較hash值,同時還要結(jié)合equles 方法比較。

HashSet 中的add ()方法會使用HashMap 的put()方法。

HashMap 的 key 是唯一的,由源碼可以看出 HashSet 添加進(jìn)去的值就是作為HashMap的key,并且在HashMap中如果K/V相同時,會用新的V覆蓋掉舊的V,然后返回舊的V。所以不會重復(fù)( HashMap 比較key是否相等是先比較hashcode 再比較equals )。

以下是HashSet 部分源碼:

private static final Object PRESENT = new Object();private transient HashMap<E, Object> map;public testCSDN198() {map = new HashMap<>();}public boolean add(E e) {// 調(diào)用HashMap的put方法,PRESENT是一個至始至終都相同的虛值return map.put(e, PRESENT) == null;}

hashCode()與equals()的相關(guān)規(guī)定:

1. 如果兩個對象相等,則hashcode一定也是相同的

2. 兩個對象相等,對兩個equals方法返回true

3. 兩個對象有相同的hashcode值,它們也不一定是相等的

4. 綜上,equals方法被覆蓋過,則hashCode方法也必須被覆蓋

5. hashCode()的默認(rèn)行為是對堆上的對象產(chǎn)生獨(dú)特值。如果沒有重寫hashCode(),則該class的兩個對象無論如何都不會相等(即使這兩個對象指向相同的數(shù)據(jù))。

==與equals的區(qū)別

1. ==是判斷兩個變量或?qū)嵗遣皇侵赶蛲粋€內(nèi)存空間 equals是判斷兩個變量或?qū)嵗赶虻膬?nèi)存空間的值是不是相同

2. ==是指對內(nèi)存地址進(jìn)行比較 equals()是對字符串的內(nèi)容進(jìn)行比較3.==指引用是否相同 equals()指的是值是否相同

2.2.3 HashSet與HashMap的區(qū)別

HashMap**HashSet*
HashMap實(shí)現(xiàn)了Map接口HashSet實(shí)現(xiàn)了Set接口
HashMap儲存鍵值對HashSet僅僅存儲對象
使用put()方法將元素放入map中使用add()方法將元素放入set中
HashMap中使用鍵對象來計(jì)算hashcode值HashSet使用成員對象來計(jì)算hashcode值,對于兩個對象來說hashcode可能相同,所以equals()方法用來判斷對象的相等性,如果兩個對象不同的話,那么返回false
HashMap比較快,因?yàn)槭鞘褂梦ㄒ坏逆I來獲取對象HashSet較HashMap來說比較慢

2.3 Queue

2.3.1BlockingQueue是什么?

Java.util.concurrent.BlockingQueue是一個隊(duì)列,在進(jìn)行檢索或移除一個元素的時候,

它會等待隊(duì)列變?yōu)榉强?#xff1b;當(dāng)在添加一個元素時,它會等待隊(duì)列中的可用空間。

BlockingQueue接口是Java集合框架的一部分,主要用于實(shí)現(xiàn)生產(chǎn)者-消費(fèi)者模式。我們不需要擔(dān)心等待生產(chǎn)者有可用的空間,或消費(fèi)者有可用的對象,因?yàn)樗荚贐lockingQueue的實(shí)現(xiàn)類中被處理了。Java提供了集中BlockingQueue的實(shí)現(xiàn),

比如ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue,、SynchronousQueue等。

在 Queue 中 poll()和 remove()有什么區(qū)別?

? 相同點(diǎn):都是返回第一個元素,并在隊(duì)列中刪除返回的對象。

? 不同點(diǎn):如果沒有元素 poll()會返回 null,而 remove()會直接拋出NoSuchElementException 異常。

代碼示例:

Queue queue = new LinkedList();queue.offer("string"); System. out. println(queue.poll()); System. out. println(queue. remove()); System. out. println(queue. size());

下一期:介紹 Java 集合容器篇面試題(下)

Java項(xiàng)目實(shí)戰(zhàn)分享:

基于java+springboot+mybatis+laiyu實(shí)現(xiàn)學(xué)科競賽管理系統(tǒng)

基于java ssm springboot+VUE疫情防疫系統(tǒng)系統(tǒng)前后端分離設(shè)計(jì)和實(shí)現(xiàn)

基于java springboot+mybatis電影售票網(wǎng)站管理系統(tǒng)前臺+后臺設(shè)計(jì)和實(shí)現(xiàn)

基于java ssm springboot+mybatis酒莊內(nèi)部管理系統(tǒng)設(shè)計(jì)和實(shí)現(xiàn)

基于JAVA springboot+mybatis智慧生活分享平臺設(shè)計(jì)和實(shí)現(xiàn)

基于Java springboot+vue+redis前后端分離家具商城平臺系統(tǒng)設(shè)計(jì)和實(shí)現(xiàn)

查看更多博主首頁更多實(shí)戰(zhàn)項(xiàng)目 >>>

總結(jié)

以上是生活随笔為你收集整理的Java 集合容器篇面试题(上)-王者笔记《收藏版》的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。