程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> Thinking in Java:容器深入研究

Thinking in Java:容器深入研究

編輯:JAVA綜合教程

Thinking in Java:容器深入研究


這裡寫圖片描述編程風格而言,應該在覆蓋equals方法時,總是同時覆蓋hashCode()方法。

3.如果一個對象被用於任何種類的排序容器中,如SortedSet(TreeSet是其唯一實現),則其必須實現Comparable接口
PS:在接口的實現方法compareTo()中,不應該使用return i-i2這樣的形式,錯誤編程,因為這樣沒有考慮到i-i2數值溢出的問題,應該
return (arg.i < i ? -1 : (arg.i == i ? 0 : 1))

4若在HashSet容器中元素並沒有重新定義hashCode(),將它們放置到任何散列實現中都可能會產生重復值,這甚至不會產生運行時錯誤。唯一的可靠方法就是寫單測。

5.SortedSet的意思為“按照對象的比較函數對元素排序”,而不是“元素插入的次序”。

6.優先級隊列,其元素排序順序也是通過實現Comparable而進行控制的。

理解Map:
1:HashMap : 基於散列表的實現。可以通過構造器設置容量和負載因子調整容器性能。
2:LinkedHashMap :與HashMap卻別在於迭代遍歷時,取得鍵值對順序是插入次序,或是LRU次序。除了迭代訪問時其余性能要慢一點
3:TreeMap:基於紅黑樹的實現。查看“鍵”或者“鍵值對”的時候,它們會被排序(按照Comparable方法),其唯一的帶有subMap()方法的Map,可以返回一個子樹。
4:WeakHashMap:弱鍵映射,允許釋放映射所指向的對象;如果映射之外沒有引用指向某個“鍵”,則此鍵可以被垃圾收集器回收
5:IdentityHashMap:使用==代替equals()對”鍵“進行比較的散列映射
PS:任何鍵都必須具有一個equals方法,如果鍵被用於散列Map,則還必須有一個恰當的hashCode方法;若鍵被用於TreeMap,則它必須實現Comparable

7.map中可以直接打印values方法的結果,該方法會產生一個包含Map中所有值得Collection,由於這些Collection背後是由Map支持的,所以對Collection的任何改動都會反映到與之相關聯的Map。

8.LinkedHashMap散列化所有的元素,但是在遍歷鍵值對時,卻又以元素的插入順序返回鍵值對,此外,可以在構造器中設定LinkedHashMap,使之采用基於訪問的LRU算法,於是沒有被訪問過的元素就會出現在隊列的前面。對於需要定期清理元素以節省空間的程序來說,此功能使得程序很容易得以實現。

散列與散列碼:
1.Object的hashCode()方法生成散列碼,而它默認是使用對象的地址計算散列碼。
2.可能你會認為,只需編寫恰當的hashCode()方法的覆蓋版本即可。但是它仍然無法正常運行,除非你同時覆蓋equals()方法,他也是Object的一部分。HashMap使用equals()判斷當前的鍵是否與表中存在的鍵相同。
PS:正確的equals()方法必須滿足下列5個條件:
1)自反性:x.equals(x)一定返回true
2)對稱性:x.equals(y)返回true當且僅當y.equals(x)
3)傳遞性:x.equals(y)且y.equals(z),則x.equals(z)為true
4)一致性:若x.equals(y)返回true,則不改變x,y時多次調用x.equals(y)都返回true
5)對於任意的非空引用值x,x.equals(null)一定返回false。

為了速度而散列:
1.由於瓶頸位於鍵的查詢速度,因此解決方案之一就是保持鍵的排序狀態,然後使用Collections。binarySearch()進行查詢
2.散列則更進一步,它將鍵保存在某處,以便能夠很快找到。存儲一組元素最快的數據結構是數組,所以使用它來表示鍵的信息。信息就是散列碼。
3.通常,沖突由外部鏈接處理,數組並直接保存至,而是保存值得list,然後對list中的值使用equals方法進行線性查詢。
4.進來,Java的散列函數都使用2的整數次方。對現代的處理器來說,除法與求余數是最慢的操作。使用2的整數次方長度的散列表,可用掩碼代替除法。因為get是使用最多的操作,求余數的%操作是其開銷最大的部分,而是用2的整數次方可以消除此開銷。

9.設計hashCode()時最重要的因素就是:無論何時,對同一個對象調用hashCode()都應該生成同樣的值。若你的hashCode()方法依賴於對象中易變的數據,用戶就要當心了。同時,也不應該使hashCode()依賴於具有唯一性的對象信息,尤其是使用this的值,這只能產生很糟糕的hashCode()因為這樣無法生成一個新的鍵使之與put中原始的鍵值對中的鍵相同。

10.要想使hashCode使用,他必須速度快,並且有意義,也就是說,他必須基於對象的內容生成散列碼。散列碼不必是獨一無二的,但是通過hashCode()和equals,必須能夠完全確定對象的身份。

性能:
1.應該避免使用Vector(能正常工作的唯一原因,只是為了向前兼容,被適配成了List)
2TreeSet迭代通常比用HashSet要快;另外,對於插入操作,LinkedHashSet比HashSet代價更高,這是由維護鏈表所帶來額外的開銷造成的
3.Hashtable的性能大體上與HashMap相當。因為HashMap是用來替代Hashtable的。因此它們使用了相同的底層存儲和查找機制。
4.IdentityHashMap則具有完全不同的性能,因為它使用==而不是equals來比較元素。

HashMap的性能因子:
容量:表中桶位數(slot)
初始容量:表在創建時所擁有的桶位數。HashMap和HashSet都具有允許你只能初始容量的構造器。
尺寸:表中當前存儲的項數。
負載因子:尺寸/容量。HashMap和HashSet都具有允許你指定負載因子的構造器,表示負載情況達到該負載因子的水平時,容器將自動添加其容量(桶位數),實現方式是使容量大致加倍,並重新將現有對象分布到新的桶位數集中(這被稱為再散列)

Collection或Map的同步控制:
1.Collections類有辦法能夠自動同步整個容器。其語法與“unmodified*”類似。
List a = Collections.synchronizedList(new ArrayList(data));
最好如上所示,是直接將新生成的容器傳遞給了適當的“同步”方法,這樣做就不會有任何機會會暴漏出不同步的版本。

快速報錯:
Java容器有一種保護機制,能夠防止多個進程同時修改同一個容器的內容。Java容器類類庫采用快速報錯(fail fast)機制。它會探查容器上的任何除了你的進程所進行的操作以外的所有變化,一旦發現其他進程改變了容器,就會立刻拋出ConcurrentModificationException異常。如:在容器取得迭代器之後,又有東西呗放入到了該容器中
ConcurrentHashMap,CopyOnWriteArrayList、CopyOnWriteArraySet都使用了可以避免ConcurrentModificationException的技術

持有引用:
1.java.lang.ref類庫包含一組類,當存在可能會耗盡內存的大對象的時候,這些類顯得特別有用。有SoftReference、WeakReference、PhantomReference。當垃圾回收期正在考察的對象只能通過某個Reference對象才“可獲得時”,上述這些不同的派生類為垃圾回收器提供了不同級別的間接性指示
2.如果想繼續持有對某個對象的引用,希望以後還能夠訪問到該對象,但是也希望能夠允許垃圾回收器釋放它,這時就應該使用Reference對象。這樣,你可以繼續使用對象,而在內存消耗殆盡的時候又允許釋放該對象。
3.以Reference對象作為你和普通引用之間的媒介(代理),另外一定不能有普通的引用指向那個對象,這樣就能達到上述目的
4.對於SoftReference、WeakReference、PhantomReference三個引用的區別和功能,詳見JVM.
5.使用SoftReference、WeakReference時,可以選擇是否要將它們放入ReferenceQueue(用作“回收前清理工作”的工具,見JVM)。而PhantomReference只能依賴於ReferenceQueue。
6.WeakHashMap:見JVM,它被用來保存WeakReference。這該映射中,每個值只保存一份實例以節省存儲空間,且WeakHashMap允許垃圾回收器自動清理鍵和值,所以它顯得十分便利。

Java 1.0/1.1容器(了解):
1.Enmuberation:老版本的迭代器,其接口比Iterator小,但是無論如何代碼中應該盡量使用Iterator。可以通過使用Collections.enumeration()方法來從Collection生成一個Enumeration
2.Hashtable:如前所說,基本的Hashtable與HashMap很相似。盡量使用HashMap(多線程同步時仍然有很多其他的選擇)
3.BisSet:如果想要高效率地存儲大量“開/關”信息,BitSet是很好的選擇。不過它的效率僅是對空間而言;如果需要高效訪問時間,BitSet比本地數組稍慢一些,BitSet最小容量是Long:64位,若存儲的內容比較小,如8位,則BitSet浪費了一些空間。BitSet也會想普通容器一樣隨著元素的加入而擴充其容量。總的來說,若擁有一個可以命名的標志集合,那麼EnumSet通常是一種更好的選擇,因為EnumSet允許你按照名字而不是數字位的位置進行操作,因此可以減少錯誤。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved