生活随笔
收集整理的這篇文章主要介紹了
[Google Guava] 2.1-不可变集合
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
原文鏈接?譯者:沈義揚(yáng)
范例
| 01 | public?static?final?ImmutableSet<String> COLOR_NAMES = ImmutableSet.of( |
| 11 | ????Foo(Set<Bar> bars) { |
| 12 | ????????this.bars = ImmutableSet.copyOf(bars);?// defensive copy! |
為什么要使用不可變集合
不可變對(duì)象有很多優(yōu)點(diǎn),包括:
- 當(dāng)對(duì)象被不可信的庫調(diào)用時(shí),不可變形式是安全的;
- 不可變對(duì)象被多個(gè)線程調(diào)用時(shí),不存在競(jìng)態(tài)條件問題
- 不可變集合不需要考慮變化,因此可以節(jié)省時(shí)間和空間。所有不可變的集合都比它們的可變形式有更好的內(nèi)存利用率(分析和測(cè)試細(xì)節(jié));
- 不可變對(duì)象因?yàn)橛泄潭ú蛔?#xff0c;可以作為常量來安全使用。
創(chuàng)建對(duì)象的不可變拷貝是一項(xiàng)很好的防御性編程技巧。Guava為所有JDK標(biāo)準(zhǔn)集合類型和Guava新集合類型都提供了簡(jiǎn)單易用的不可變版本。
?JDK也提供了Collections.unmodifiableXXX方法把集合包裝為不可變形式,但我們認(rèn)為不夠好:
- 笨重而且累贅:不能舒適地用在所有想做防御性拷貝的場(chǎng)景;
- 不安全:要保證沒人通過原集合的引用進(jìn)行修改,返回的集合才是事實(shí)上不可變的;
- 低效:包裝過的集合仍然保有可變集合的開銷,比如并發(fā)修改的檢查、散列表的額外空間,等等。
如果你沒有修改某個(gè)集合的需求,或者希望某個(gè)集合保持不變時(shí),把它防御性地拷貝到不可變集合是個(gè)很好的實(shí)踐。
重要提示:所有Guava不可變集合的實(shí)現(xiàn)都不接受null值。我們對(duì)Google內(nèi)部的代碼庫做過詳細(xì)研究,發(fā)現(xiàn)只有5%的情況需要在集合中允許null元素,剩下的95%場(chǎng)景都是遇到null值就快速失敗。如果你需要在不可變集合中使用null,請(qǐng)使用JDK中的Collections.unmodifiableXXX方法。更多細(xì)節(jié)建議請(qǐng)參考“使用和避免null”。
怎么使用不可變集合
不可變集合可以用如下多種方式創(chuàng)建:
- copyOf方法,如ImmutableSet.copyOf(set);
- of方法,如ImmutableSet.of(“a”, “b”, “c”)或 ImmutableMap.of(“a”, 1, “b”, 2);
- Builder工具,如
| 1 | public?static?final?ImmutableSet<Color> GOOGLE_COLORS = |
| 2 | ????????ImmutableSet.<Color>builder() |
| 3 | ????????????.addAll(WEBSAFE_COLORS) |
| 4 | ????????????.add(new?Color(0,?191,?255)) |
此外,對(duì)有序不可變集合來說,排序是在構(gòu)造集合的時(shí)候完成的,如:
| 1 | ImmutableSortedSet.of("a",?"b",?"c",?"a",?"d",?"b"); |
會(huì)在構(gòu)造時(shí)就把元素排序?yàn)閍, b, c, d。
比想象中更智能的copyOf
請(qǐng)注意,ImmutableXXX.copyOf方法會(huì)嘗試在安全的時(shí)候避免做拷貝——實(shí)際的實(shí)現(xiàn)細(xì)節(jié)不詳,但通常來說是很智能的,比如:
| 1 | ImmutableSet<String> foobar = ImmutableSet.of("foo",?"bar",?"baz"); |
| 4 | void?thingamajig(Collection<String> collection) { |
| 5 | ????ImmutableList<String> defensiveCopy = ImmutableList.copyOf(collection); |
在這段代碼中,ImmutableList.copyOf(foobar)會(huì)智能地直接返回foobar.asList(),它是一個(gè)ImmutableSet的常量時(shí)間復(fù)雜度的List視圖。
作為一種探索,ImmutableXXX.copyOf(ImmutableCollection)會(huì)試圖對(duì)如下情況避免線性時(shí)間拷貝:
- 在常量時(shí)間內(nèi)使用底層數(shù)據(jù)結(jié)構(gòu)是可能的——例如,ImmutableSet.copyOf(ImmutableList)就不能在常量時(shí)間內(nèi)完成。
- 不會(huì)造成內(nèi)存泄露——例如,你有個(gè)很大的不可變集合ImmutableList<String>
hugeList, ImmutableList.copyOf(hugeList.subList(0, 10))就會(huì)顯式地拷貝,以免不必要地持有hugeList的引用。 - 不改變語義——所以ImmutableSet.copyOf(myImmutableSortedSet)會(huì)顯式地拷貝,因?yàn)楹突诒容^器的ImmutableSortedSet相比,ImmutableSet對(duì)hashCode()和equals有不同語義。
在可能的情況下避免線性拷貝,可以最大限度地減少防御性編程風(fēng)格所帶來的性能開銷。
asList視圖
所有不可變集合都有一個(gè)asList()方法提供ImmutableList視圖,來幫助你用列表形式方便地讀取集合元素。例如,你可以使用sortedSet.asList().get(k)從ImmutableSortedSet中讀取第k個(gè)最小元素。
asList()返回的ImmutableList通常是——并不總是——開銷穩(wěn)定的視圖實(shí)現(xiàn),而不是簡(jiǎn)單地把元素拷貝進(jìn)List。也就是說,asList返回的列表視圖通常比一般的列表平均性能更好,比如,在底層集合支持的情況下,它總是使用高效的contains方法。
細(xì)節(jié):關(guān)聯(lián)可變集合和不可變集合
| 可變集合接口 | 屬于JDK還是Guava | 不可變版本 |
| Collection | JDK | ImmutableCollection |
| List | JDK | ImmutableList |
| Set | JDK | ImmutableSet |
| SortedSet/NavigableSet | JDK | ImmutableSortedSet |
| Map | JDK | ImmutableMap |
| SortedMap | JDK | ImmutableSortedMap |
| Multiset | Guava | ImmutableMultiset |
| SortedMultiset | Guava | ImmutableSortedMultiset |
| Multimap | Guava | ImmutableMultimap |
| ListMultimap | Guava | ImmutableListMultimap |
| SetMultimap | Guava | ImmutableSetMultimap |
| BiMap | Guava | ImmutableBiMap |
| ClassToInstanceMap | Guava | ImmutableClassToInstanceMap |
| Table | Guava | ImmutableTable |
原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明:?轉(zhuǎn)載自并發(fā)編程網(wǎng) – ifeve.com本文鏈接地址:?[Google Guava] 2.1-不可變集合
from:?http://ifeve.com/google-guava-immutablecollections/?
總結(jié)
以上是生活随笔為你收集整理的[Google Guava] 2.1-不可变集合的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。