Immutable Collections
不可變對象有很多優點
1.對於不信任的庫使用安全
2.對於多線程不會出現多個線程競態的情況
3.不需要支持變化,使得在空間和時間上都能夠固定下來,不可變的對象在內存方面更加高效
4.可以作爲常量使用
對於對象的不可變拷貝是編程的一種防禦式方法,guava提供了對於collection中每個類型簡單,方便的不可變拷貝,包含guava的集合變量不可變拷貝。
比較jdk和guava中的不可變集合
jdk中提供了collections.unmodifiablexxx 方式,但是看來,有以下缺點
- 不夠廣泛而冗長,不能在想要做拷貝的任何地方使用
- 不安全:如果沒有持有原有對象的引用,返回的集合不可變
- 不夠高效:上面還有可變集合的數據結構的方面,有修改的併發檢查,使用到hash 表中額外的空間。
- 當你不期望修改一個集合,或者一個集合作爲常量使用,一個好的方法就是將它拷貝成不可變的另一個集合
創建不可變對象
- 使用copyof方式,ImmutableSet.copyOf(set)
- 使用of的方式,ImmutableSet.of("a","b","c") ImmutableMap.of("a",1,"b",2)
- 使用構造器模式Builder
eg
build方法
public static final ImmutableSet<Color> GOOGLE_COLORS = ImmutableSet.<Color>builder()
.add(new Color(0, 191, 255))
.build();
期望排過序的集合,構造集合的時候,順序已經保存了下來
ImmutableSet.of("a","b","c","d");
copyOf方法
ImmutableSet<String> foobar = ImmutableSet.of("foo", "bar", "baz");
public ImmutableList doCopy(Collection<String> collection) {
return ImmutableList.copyOf(collection);
}
public void testImmutableList(){
doCopy(foobar);
}
上面的代碼中,ImmutableList.copyOf(foobar) 足夠智能的返回了foobar.asList(),在ImmutableSet看來是常數時間類型
通常的啓發式當中,ImmutableXXX.copyOf(ImmutableCollection)試着避免線性時間拷貝
1.可以在常數時間內使用已定義的數據結構,如ImmutableSet.copyOf(ImmutableList) 不能夠在線性時間內完成
2.不會引起內存泄漏,例如,如果有一個大的不可變列表,使用了ImmutableLIst.copyOf(hugeList.subLIst(0,10)),一個明確的拷貝被執行,避免突然持有對整個hugeList的引用;
3.不會改變語義,ImmutableSet.copyOf(myImmutableSortedSet)執行精確的拷貝,因爲ImmutableSet使用的hashCode和equals與ImmutableSortedSet在基於比較方面有不同的語義含義。
這些減少了防禦性編程style性能方面消耗
asList
所有不變的集合通過asList()提供了不變的列表,例如,有保存在ImmutableSortedSet中的數據,可以使用sortedSet.asLIst().get(k)獲取第k小的元素
ImmutableList是頻繁的,不經常的,通常看作一個常量,而不是一個精確的複製,它比普通的list更高效,例如,可以使用返回數據集合中更高效的contains方法。