什么是不可變集合把敞?
比如我們想創(chuàng)建一個(gè)list集合弥奸,想讓這個(gè)list不能在被做任何修改了,這時(shí)候我們就可以用Guava包里ImmutableSet來(lái)創(chuàng)建一個(gè)list
例子:
public static final ImmutableSet<String> COLOR_NAMES = ImmutableSet.of(
"red",
"orange",
"yellow",
"green",
"blue",
"purple");
不可變集合有哪些好處呢先巴?
- 當(dāng)對(duì)象被不可信的庫(kù)調(diào)用時(shí)其爵,不可變形式是安全的;(可以交給任意邏輯去)
- 不可變對(duì)象被多個(gè)線程調(diào)用時(shí)伸蚯,不存在競(jìng)態(tài)條件問(wèn)題(不存在多線程里的線程安全問(wèn)題)
- 不可變集合不需要考慮變化摩渺,因此可以節(jié)省時(shí)間和空間。所有不可變的集合都比它們的可變形式有更好的內(nèi)存利用率(分析和測(cè)試細(xì)節(jié))剂邮;(節(jié)省空間)
- 不可變對(duì)象因?yàn)橛泄潭ú蛔円』茫梢宰鳛槌A縼?lái)安全使用。(作為常量)
不僅Guava包提供了不可變集合的版本,jdk本身也提供了Collecitons.unmodifiableXXXX方法來(lái)把集合變成不可變的形式绰姻,但JDK的有以下幾個(gè)缺點(diǎn):
- 笨重累贅枉侧,需要寫(xiě)的代碼太多了。
- 不安全狂芋,如果通過(guò)原集合的引用來(lái)進(jìn)行集合里元素的修改其實(shí)也是可以修改的榨馁,導(dǎo)致可變了。
- 效率較低帜矾。被包裝過(guò)的集合本質(zhì)上還是使用著原來(lái)集合的方法翼虫,導(dǎo)致比如并發(fā)修改list還是會(huì)有一些檢查,HashMap里還有一些沒(méi)有用的額外的屬性屡萤。其實(shí)如果集合不可變珍剑,原來(lái)集合里的一些機(jī)制就可以沒(méi)有了。
重要提示:
所有Guava不可變集合的實(shí)現(xiàn)都不接受null值死陆。我們對(duì)Google內(nèi)部的代碼庫(kù)做過(guò)詳細(xì)研究招拙,發(fā)現(xiàn)只有5%的情況需要在集合中允許null元素,剩下的95%場(chǎng)景都是遇到null值就快速失敗措译。如果你需要在不可變集合中使用null别凤,請(qǐng)使用JDK中的Collections.unmodifiableXXX方法。更多細(xì)節(jié)建議請(qǐng)參考“使用和避免null”领虹。
如果使用呢闻妓?
- 使用copyOf方法,例子:ImmutableSet.copyOf(set)
- of方法掠械,ImmutableSet.of("1","2") 或者ImmutableMap.of("key1","value1","key2","value2");
- Builder工具由缆,例子:ImmutableXXXX.builder().add().builder();
asList視圖
所有不可變集合都有一個(gè)asList()方法提供ImmutableList視圖,來(lái)幫助你用列表形式方便地讀取集合元素猾蒂。例如均唉,你可以使用sortedSet.asList().get(k)從ImmutableSortedSet中讀取第k個(gè)最小元素。
asList()返回的ImmutableList通常是——并不總是——開(kāi)銷穩(wěn)定的視圖實(shí)現(xiàn)层扶,而不是簡(jiǎn)單地把元素拷貝進(jìn)List。也就是說(shuō)烙荷,asList返回的列表視圖通常比一般的列表平均性能更好镜会,比如,在底層集合支持的情況下终抽,它總是使用高效的contains方法