java有序不重復(fù)的集合 Java遍歷HashSet時,為什么輸出是有序的?
Java遍歷HashSet時,為什么輸出是有序的?首先,上面是hash的類描述,表示hash可以是無序的,也可以是有序的。問一下會是什么樣子,讓我們看看HashSet的源代碼實現(xiàn)。HashSet的底層
Java遍歷HashSet時,為什么輸出是有序的?
首先,上面是hash的類描述,表示hash可以是無序的,也可以是有序的。問一下會是什么樣子,讓我們看看HashSet的源代碼實現(xiàn)。
HashSet的底層由具有空鍵的HashMap存儲。
HashMap的數(shù)據(jù)結(jié)構(gòu)是table[entry],這是一個鏈表結(jié)構(gòu),每個數(shù)據(jù)元素都是一個鏈表。具有相同hashcode的不同鍵將落在表[hashcode]的鏈表上。
但是當(dāng)HashMap存儲值時,它將根據(jù)密鑰的hashcode()計算存儲位置(該位置是散列的,所以它是無序的);
它感覺是有序的,因為hashcode()不重復(fù)。如果不要求ID是數(shù)字,建議使用最簡單的一個,即UUID,它包括機器代碼、時間戳、隨機數(shù)等,但UUID最終生成一個全局唯一的字符串,而不是整數(shù),并且看起來順序不對。
2. MySQL自己添加ID。它使用一個表來存儲各種業(yè)務(wù)id。每個分布式系統(tǒng)插入一個ID后,生成1000萬個本地號碼與ID拼接,然后每個系統(tǒng)得到一個ID,相當(dāng)于生成1000萬個ID,足夠長時間使用。這1000萬個ID可以預(yù)先定義,并在系統(tǒng)啟動時放入內(nèi)存。因為它們只是ID,所以不會占用太多內(nèi)存。MySQL可以內(nèi)置到集群中,這不會影響自增IDs的使用。
3. 與MySQL的auto-increment ID類似,redis的incr實現(xiàn)了自動增量。每個分布式系統(tǒng),比如redis,都是用incr插入一個ID,然后生成1000萬個本地號碼與ID拼接,如果每個系統(tǒng)都有一個ID,相當(dāng)于生成1000萬個ID,足夠長時間使用。這1000萬個ID可以預(yù)先定義,并在系統(tǒng)啟動時放入內(nèi)存。因為它只是一個ID,所以不會占用太多內(nèi)存。Redis也可以內(nèi)置到集群中,這不會影響自增ID的使用。Twitter的雪花算法與UUID類似,包括機器碼、時間戳、隨機數(shù)等,但最終生成的是64位整數(shù),可以滿足許多分布式系統(tǒng)的要求。如果Id必須是整數(shù),建議使用snowflake而不是UUID。
javaWeb 在系統(tǒng)高并發(fā)的情況下生成有序流水號?
1. Linkedhashset繼承自hahsset。構(gòu)造方法使用三個參數(shù)調(diào)用方法。構(gòu)造方法的底層初始化LinkedHashMap。因為LinkedHashMap是有序的,所以linkedhashset也是有序的。為什么我們不能調(diào)用這個構(gòu)造函數(shù)?它是包訪問級別,不能在外部調(diào)用。接下來,分析LinkedHashMap是如何實現(xiàn)的,以理解為什么它是有序的。
2. 先看下面的圖片。(對于寫在手機上的問題,你不能把圖片放在文字里,它們都在下面。)。
LinkedHashMap的數(shù)據(jù)結(jié)構(gòu)與HashMap不同。HashMap中的條目有四個屬性:key、value、hash和next,而LinkedHashMap中的條目添加了before和after屬性。因此,LinkedHashMap在HashMap的基礎(chǔ)上使用雙向鏈表來連接所有節(jié)點。當(dāng)然,它也有一個頭部節(jié)點,所以遍歷可以有序進行。具體結(jié)構(gòu)如圖所示。
3. LinkedHashMap主要重寫addentry和createentry方法,在創(chuàng)建節(jié)點時創(chuàng)建雙向鏈表。
此外,LinkedHashMap還可以實現(xiàn)LRU算法的緩存。
源代碼基于JDK7查看ha。如果你不懂HashMap,你可以看到我分享的另一篇文章。
希望對您有所幫助,您可以關(guān)注我,以后會分享更多的架構(gòu)和java知識文章。