前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。
ImmutableCollection代碼定義
@GwtCompatible(emulated=true)
public abstract class ImmutableCollection<E> extends AbstractCollection<E> implements Serializable
- ?
ImmutableCollection表示內容不可更改的集合,并提供以下額外特性的擔保。
注意:應當避免直接使用ImmutableCollection作為一個類型,就如同避免直接使用Collection本身一樣。最好使用其子類(例如ImmutableSet或ImmutableList),因為子類擁有更好的Object.equals(java.lang.Object)?語義,可以從源頭避免常見的bug和錯誤。
以下文檔適用于com.google.common.collect包中所有公開的不可變類型,不論是否是ImmutableCollection的子類。
保證特性
- 淺不可變:
淺不可變是指值是不可寫的,但是如果是對象的引用的值是可被改變的。不能對不可變集合的元素進行增加、移除或者替換。這是比Collections.unmodifiableCollection?更嚴格的保證,因為這個集合的內容會隨其包裝集合的改變而改變。
- 不可為Null:
本集合不能包含null元素。
- 確定性的迭代?:
元素迭代順序是被定義的,取決于集合的創建(細節可以參考對應的工廠方法)。除非另外注明,集合視圖(例如ImmutableMultiset.elementSet())的迭代順序與父集合一樣。
- 線程安全:
多線程并發訪問集合是安全的。
- 完整性:
本類型不能在除com.google.common.collect包以外被繼承。(因為這有可能違反以上擔保特性。)
接口而非實現
每一個公開的類(例如ImmutableSet)都是一個提供具體功能行為保證的類型,而不僅僅是在某種特定的實現(例如ArrayList)。對類型名稱的含義都應當理解為是接口而非實現。
屬性類型和方法返回類型通常都應當使用不可變類型(例如ImmutableList)而不是一般的集合接口(例如List)。這樣便于告知調用者以上對于類型的保證特性,這是非常有用的信息。
另一方面,直接將ImmutableList作為參數類型并不令人滿意。解決方案是接受Iterable類型參數,通過方法或構造器將它傳遞給相應的copyOf方法。
創建
除了邏輯層面的抽象類(例如ImmutableCollection),每個不可變類型都提供了或者此類型實例的靜態方法。最常用的有:?
1、靜態方法of,接受一個顯示的元素或條目列表。?
2、靜態方法copyOf(或者copyOfSorted),接受一個內容可被復制的已存在的集合。?
3、嵌套的靜態類Builder,它可以用來填充一個新的不可變實例。
警告
如任何集合一樣,改變集合中的元素(這種改變影響了Object.equals(java.lang.Object)的行為)是一種錯誤的做法。他會引起未定義的行為和bug。通常最佳實踐是完全避免使用可變對象作為集合元素,雖然許多用戶認為不可變對象是深不可變的(deeply immutable)。
性能說明
1、集合的實現通常優先考慮內存效率,然后是訪問速度,最后是創建速度。?
2、copyOf方法有時會認為沒有必要進行實際復制操作:例如,copyOf(copyOf(anArrayList))只會復制一次。這減少了在API邊界習慣性地創建防御副本的代價。但是,跳過拷貝操作的精確情況是未定義的。?
3、警告:視圖集合(例如ImmutableMap.keySet或ImmutableList.subList(int,int))會保留對整個數據集合的引用,以防止其被垃圾收集。如果其中一些數據通過其他方式不再可用,這可能會產生內存泄漏。可通過傳遞視圖集合給適當的copyOf方法以獲得正確大小的拷貝。?
4、與創建可變集合并拷貝相比,使用相應關聯的Builder類并不會降低性能,有可能會更好。?
5、通常實現不會緩存hash code。如果元素或鍵類型的hashCode實現較慢,它應當自己實現緩存。
使用示例
class Foo {private static final ImmutableSet<String> RESERVED_CODES =ImmutableSet.of("AZ", "CQ", "ZX");private final ImmutableSet<String> codes;public Foo(Iterable<String> codes) {this.codes = ImmutableSet.copyOf(codes);checkArgument(Collections.disjoint(this.codes, RESERVED_CODES));}}
?