集合中的線程初體驗

java零基礎(chǔ)入門-高級特性篇(四)? HashSet 和 Collections

本章繼續(xù)講集合,先來看看Set集合。Set集合的特點,1:無序,2:無重復(fù)。上一章講了HashMap,最后提到HashSet的底層實現(xiàn)其實就是HashMap。那么為什么用HashMap就可以實現(xiàn)無序和不重復(fù),下面看看具體如何使用HashMap實現(xiàn)HashSet。

hashset和hashmap的區(qū)別

hashset底層用hashmap實現(xiàn),那為什么不直接用hashmap就完了,非要整個hashset出來?

集合

如果有這個問題,可以回頭看看前面講的集合框架的設(shè)計。設(shè)計hashset是用來保存那種不需要使用下標(biāo)操作元素,并且不能重復(fù)的集合。set集合的元素和List集合的元素一樣,都是一個對象。而hashmap的元素是key-value鍵值對,因為數(shù)據(jù)存儲類型不同,所以需要將set和map區(qū)分開來??匆幌聢D,幫助回憶一下。

hashmap如何實現(xiàn)hashset

Set集合最重要的一個方法就是add(E e),如何往一個Set集合添加元素,了解了添加元素的原理,查找元素理解起來就簡單許多。hashset的add方法,用的就是是hashmap的put方法。下面是源代碼:

map.put(e,PRESENT) == null

這里需要重點理解的是,一個對象如何存入一個key-value。從上面這句代碼中,可以發(fā)現(xiàn),在往set集合添加元素的時候,這個元素被用來當(dāng)做map的key,而value是一個常量。

為什么直接將對象作為key呢?因為hashmap使用哈希算法對key進(jìn)行計算,計算后的結(jié)果就是底層數(shù)組的位置,所以當(dāng)使用hashset的時候,需要對放進(jìn)set的對象進(jìn)行哈希計算,至于value,hashset不關(guān)心。

hashmap的key的特性就是不會重復(fù),后添加相同的數(shù)據(jù)會將前一個數(shù)據(jù)覆蓋掉。正好滿足了set集合不重復(fù)的特性,所以直接用hashmap即可以滿足hashset集合的要求。


關(guān)系

其實這里容易繞暈的是幾個底層實現(xiàn)的結(jié)構(gòu),這里用一個圖來說明一下。HashSet利用HashMap的Key的特性來實現(xiàn),而HashMap是利用數(shù)組和鏈表的特性來實現(xiàn),這樣應(yīng)該明白這幾個結(jié)構(gòu)之間的關(guān)系了吧。

這次hashset真的講完了。

Collections工具

使用集合存放數(shù)據(jù)的時候,會有很多情況要對集合進(jìn)行操作。特別是List集合,因為List集合的有序性,會需要按照特定的順序操作集合,而java也專門提供了Collections工具來對集合進(jìn)行操作。下面來看看幾個例子

List list = new ArrayList();

list.add("one");//此處省略 ,一共添加五個元素one,two,three,fore,five

Collections方法

Collection.reverse(list);//反轉(zhuǎn)集合元素的順序

Collection.shuffle(list);//隨機順序,多次隨機結(jié)果可能不一樣

Collection.sort(list);//升序排序,先數(shù)字后字母,數(shù)字0-9,字母A-Z a-z的順序,逐位比較

Collection.swap(list,0,3);//交換第一個和第四個元素位置

看一個swap的源碼實現(xiàn)

Object tmp = arr[i];

arr[i] = arr[j];

arr[j] = temp;

嗯,完了,是不是有一種這玩意我都會寫,干嘛要用這個的感覺?其實確實可以自己寫,但是一般提供工具給別人用,肯定要提供全套,再就是合理的使用工具會減少不必要的代碼,提升代碼的可讀性。

Collection 和 Collections

這兩個長得很像,但是作用差別很大,初學(xué)者切勿將兩者概念混淆。Collection是集合體系中的上層接口,而Collections是操作集合的工具。何謂工具?還記不記得我們講的靜態(tài)方法?不記得的快去復(fù)習(xí)類和對象的文章。

Collections作為一個工具類,里面提供的方法都是靜態(tài)方法,所以在上面的例子中,都是直接使用類Collections來調(diào)用方法,Collections提供了大量的靜態(tài)方法來操作集合,有沒有加深對靜態(tài)成員這個概念的理解?

用Collections工具類創(chuàng)建線程安全的集合

上次講vector的時候,說了他是線程安全的集合,而List是線程不安全的。但是可以通過一些方法讓List變成線程安全的,所以vector目前已經(jīng)沒有使用的必要了。那么如何讓List變成線程安全的集合呢?答案就是使用Collections工具可以將List變?yōu)榫€程安全。

Collections有一系列的synchronized方法來使集合變?yōu)榫€程安全的,一系列是指不僅僅可以將List變?yōu)榫€程安全的,Set,Map也有方法變成線程安全的。

List list = Collections.synchronizedList(new ArrayList());

Set set = Collections.synchronizedSet(new HashSet());

Map map = Collections.synchronizedMap(new HashMap());

使用以上三個工具方法就可以將普通集合變?yōu)榫€程安全的集合。這些方法有什么魔法么,為什么外面包一層就線程安全了?下面來簡單介紹一下多線程以及使用多線程會遇到的問題。

多線程是什么?

多線程就是并行處理問題。比如去銀行取錢,如果只有一個取款機隊伍就會排很長,但是如果有多個取款機同時辦理業(yè)務(wù),速度就會快很多。這就是多線程的思路,多個線程(取款機)處理一個問題(取錢)。

多個ATM

為什么多線程有安全問題?

假設(shè)現(xiàn)在有2個人要取款,如果2個人同時操作一個取款機會發(fā)生什么?第一個人密碼輸了3位數(shù),第二個人跑來按3位數(shù),第一個人刪了準(zhǔn)備重新輸,又被第二個人按了3下,這樣下去兩個人都別想取錢。多個線程搶同一個資源就會產(chǎn)生線程安全問題,實際開發(fā)中遇到的線程安全問題會比這種情況還要復(fù)雜。

怎么解決?

帶鎖的ATM

新款取款機,帶門帶鎖的!一旦一個人進(jìn)去了,先鎖門,然后就可以放心大膽的取錢了,這時候沒有人會來跟你搶著取錢了。代碼里面也是可以上鎖的,所以線程安全的集合都是帶有鎖機制的。

高效并發(fā)容器

這里是補充知識,了解即可。其實上面的這幾個方法確實可以將普通集合轉(zhuǎn)為線程安全的集合,但是實現(xiàn)很粗糙,導(dǎo)致效率不是很高。所以就有了專門為并發(fā)情況設(shè)計的更加高效的并發(fā)容器,比如CopyOnWriteArrayList,CopyOnWriteArraySet,ConcurrentHashMap。

上鎖也是有很多種上鎖的方法,繼續(xù)取錢的例子。

最極端粗暴的上鎖方式就是,銀行每次只準(zhǔn)進(jìn)一個人,這樣絕對不會有任何問題,絕對安全,銀行所有保安都盯著你,你還能玩出花來?但是這樣做效率極端底下。比如老版本的vector和hashtable就是用類似這種粗暴的方法來上鎖。

再來看稍微先進(jìn)點的上鎖方式。就是銀行可以進(jìn)很多人,但是辦理不同業(yè)務(wù)的分開來,取錢的一個隊,存錢的一個隊,辦理財換密碼再來一個隊,每個隊同時只能一個人辦,辦的人進(jìn)小房間,上鎖。這種上鎖的粒度比上面那種要小,效率要快很多。

最后就是最先進(jìn)的鎖了。也就是類似并發(fā)容器這種,升級版的取款機不僅可以取錢還可以存錢,還能辦其他業(yè)務(wù)~也就是說不管辦什么業(yè)務(wù),找個人最少的隊排著就行了,所有機器可以同時辦相同或者不同的業(yè)務(wù)。這種鎖的粒度最小,只對操作對象的數(shù)據(jù)進(jìn)行上鎖,效率最高。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Java集合類可用于存儲數(shù)量不等的對象,并可以實現(xiàn)常用的數(shù)據(jù)結(jié)構(gòu)如棧,隊列等,Java集合還可以用于保存具有映射關(guān)...
    小徐andorid閱讀 2,089評論 0 13
  • 原文地址 Java集合 Java集合框架:是一種工具類,就像是一個容器可以存儲任意數(shù)量的具有共同屬性的對象。 Ja...
    gyl_coder閱讀 1,040評論 0 8
  • Collection ├List │├LinkedList │├ArrayList │└Vector │└Stac...
    AndyZX閱讀 963評論 0 1
  • 在一個方法內(nèi)部定義的變量都存儲在棧中,當(dāng)這個函數(shù)運行結(jié)束后,其對應(yīng)的棧就會被回收,此時,在其方法體中定義的變量將不...
    Y了個J閱讀 4,575評論 1 14
  • 周末陪娃上課外班的時候,談?wù)剫屢贿厱駜鹤拥睦L畫作品,一邊吐槽對學(xué)校教育的不滿: 你們不知道,現(xiàn)在私立小學(xué)一年級就開...
    職場二寶媽頻道閱讀 573評論 0 0

友情鏈接更多精彩內(nèi)容