深入理解LinkedHashSet集合的底層機(jī)制
LinkedHashSet 能夠維護(hù)元素插入集合的順序,在遍歷時(shí),按照此順序進(jìn)行遍歷。
LinkedHashSet 繼承了 HashSet 類,實(shí)現(xiàn)了 Set 等接口。LinkedHashSet 仍然支持 null 元素,唯一有所區(qū)別的是在迭代時(shí),它能夠按照元素的插入順序遍歷。
LinkedHashSet 的實(shí)現(xiàn)非常簡單,它僅僅只重新實(shí)現(xiàn)了構(gòu)造方法,將 HashSet 內(nèi)部維護(hù)的 HashMap 對象變?yōu)榱?LinkedHashMap 對象。
public LinkedHashSet(int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor, true); } public LinkedHashSet(int initialCapacity) { super(initialCapacity, .75f, true); } public LinkedHashSet() { super(16, .75f, true); } public LinkedHashSet(Collection<? extends E> c) { super(Math.max(2*c.size(), 11), .75f, true); addAll(c); }
不難發(fā)現(xiàn),這里僅僅調(diào)用了父類的同一個(gè)構(gòu)造方法,查看父類的該構(gòu)造方法:
HashSet(int initialCapacity, float loadFactor, boolean dummy) { map = new LinkedHashMap<>(initialCapacity, loadFactor); }
這里至少有三點(diǎn),我們可以注意到:
訪問控制修飾符為默認(rèn),也就是說 我們并不能直接通過該構(gòu)造函數(shù)創(chuàng)建 HashSet 對象實(shí)例,否則創(chuàng)建出來的對象實(shí)例就是有序(插入順序)的了。同時(shí),也能看出,我們繼承 HashSet 也無法獲得該構(gòu)造函數(shù);如果想要實(shí)現(xiàn)自己的HashSet,并且具有有序這一特性,應(yīng)該考慮從 LinkedHashSet 繼承。dummy 參數(shù),該參數(shù)的作用是為了區(qū)分方法簽名,因?yàn)?HashSet 已經(jīng)存在 HashSet(int,float) 這樣的構(gòu)造函數(shù)了。內(nèi)部維護(hù)的 HashMap 實(shí)例變?yōu)榱?LinkedHashMap 對象的實(shí)例。
所以,LinkedHashSet 的有序性是將父類內(nèi)部維護(hù)的 HashMap 實(shí)例更換為 LinkedHashMap 實(shí)例實(shí)現(xiàn)的,它并不需要重寫任何其它的方法。
還有個(gè)值得注意的問題,LinkedHashMap 是支持兩種排序的,一種是 插入排序(也就是現(xiàn)在這種),一種是訪問排序(構(gòu)造函數(shù)中設(shè)置 accessOrder 為 true);
既然知道了它的實(shí)現(xiàn)原理也不難理解為什么它能夠按插入順序進(jìn)行迭代了,因?yàn)樗耆珡?fù)用了 LinkedHashMap的部分功能。
我們知道通過迭代器遍歷是可以按插入順序,那么通過 forEach 方法或者 Java 的 增強(qiáng) for 循環(huán)能否有序呢?其實(shí)這兩種方法本質(zhì)上都與 java.lang.Iterable 接口有關(guān),Collection 接口實(shí)現(xiàn)了這個(gè)接口,該接口提供了返回迭代器的方法,所以歸根結(jié)底,這兩種方法也可以算迭代器遍歷。 HashSet 實(shí)現(xiàn)了 Iterable 接口的方法,返回指定 HashMap 對象實(shí)例的迭代器,所以在使用 LinkedHashSet 的 forEach 方法或者增強(qiáng) for 循環(huán)時(shí),仍然能夠按插入順序遍歷。
forEach 是Iterable接口的默認(rèn)方法,默認(rèn)實(shí)現(xiàn)使用了增強(qiáng) for 循環(huán);增強(qiáng) for 循環(huán)還可用于數(shù)組。
到此這篇關(guān)于深入理解LinkedHashSet集合的底層機(jī)制的文章就介紹到這了,更多相關(guān)LinkedHashSet底層機(jī)制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
通過jstack分析解決進(jìn)程死鎖問題實(shí)例代碼
這篇文章主要介紹了通過jstack分析解決進(jìn)程死鎖問題實(shí)例代碼,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-01Java中的字節(jié)流InputStream和OutputStream詳解
這篇文章主要介紹了Java中的字節(jié)流InputStream和OutputStream詳解,繼承自InputStream的流都是用于向程序中輸入數(shù)據(jù),且數(shù)據(jù)的單位為字節(jié)8bit,我們看到的具體的某一些管道,凡是以InputStream結(jié)尾的管道,都是以字節(jié)的形式向我們的程序輸入數(shù)據(jù),需要的朋友可以參考下2023-10-10利用Java查看進(jìn)程內(nèi)存占用情況的實(shí)現(xiàn)方法
在系統(tǒng)監(jiān)控和性能調(diào)優(yōu)中,了解各個(gè)進(jìn)程的內(nèi)存占用情況是非常重要的一環(huán),通過查看進(jìn)程內(nèi)存使用情況,開發(fā)者和運(yùn)維人員可以及時(shí)發(fā)現(xiàn)異常進(jìn)程、資源瓶頸和內(nèi)存泄漏問題,本項(xiàng)目旨在使用 Java 編寫一個(gè)簡單的程序,通過調(diào)用操作系統(tǒng)的命令來獲取系統(tǒng)中各個(gè)進(jìn)程的內(nèi)存使用情況2025-03-03SpringBoot項(xiàng)目運(yùn)行jar包啟動(dòng)的步驟流程解析
這篇文章主要介紹了SpringBoot項(xiàng)目運(yùn)行jar包啟動(dòng)的步驟流程,本文分步驟通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2020-07-07java 實(shí)現(xiàn)定時(shí)的方法及實(shí)例代碼
這篇文章主要介紹了java 定時(shí)任務(wù)詳細(xì)介紹及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-03-03集合框架(Collections Framework)詳解及代碼示例
這篇文章主要介紹了集合框架(Collections Framework)詳解及代碼示例,文章涉及集合數(shù)組的區(qū)別,collection接口,iterator迭代器,list接口及其用法,LinkedHashSet集合等有關(guān)內(nèi)容,具有一定參考價(jià)值,需要的朋友可以了解下。2017-11-11淺談使用Java Web獲取客戶端真實(shí)IP的方法示例詳解
這篇文章主要介紹了使用Java-Web獲取客戶端真實(shí)IP的方法示例詳解。一般我們無法獲取客戶端真實(shí)IP,原因是:當(dāng)我們通過request獲取客戶端IP時(shí),自身服務(wù)器通常會為了保護(hù)信息或者負(fù)載均衡的目的,對自身服務(wù)器做反向代理。對此感興趣可以了解一下2020-07-07