《Thinking in Java》學習——17章容器深入研究(二)

理解Map

1.映射表的基本思想是它維護的是鍵-值(對)關聯才漆,因此你可以使用鍵來查找值牛曹。
2.下面是一個簡單的關聯數組的創(chuàng)建:

public class AssociativeArray<K, V> {
    private Object[][] pairs;
    private int index;
    public AssociativeArray(int length) {
        pairs = new Object[length][2];
    }
    public void put(K key, V value) {
        if (index >= pairs.length) 
            throws new ArrayIndexOutOfBoundsException();
        pairs[index++] = new Object[]{key, value};
    }
    @SupressWarning("unchecked")
    public V get(K key) {
        for (int i = 0; i < pairs.length; i++) {
            if (key.equals(pairs[i][0])) {
                return (V) pairs[i][1];
            }
        }
        return null;
    }
}

上面的代碼只是具有一定的說明性,但是缺乏效率醇滥,并且由于具有固定尺寸而顯得很不靈活黎比。

一.性能

1.HashMap使用了特殊的值,稱為散列碼鸳玩,來取代對鍵的緩慢搜索阅虫。散列碼是相對唯一的、用以代表對象的int值不跟,他是通過將該對象的某些信息進行轉換而生成的颓帝。
2.hashCode()是類Object中的方法,因此所有Java對象都能產生散列碼窝革。HashMap就是使用對象的hashCode()進行快速查詢的躲履,此方法能夠顯著提高性能。
3.下面是幾種基本的Map的實現:

Method 實現描述
HashMap Map基于散列表帶你實現(它取代了Hashtable)聊闯。插入和查詢“鍵值對”的開銷是固定的工猜。可以通過構造器設置容量和負載因子菱蔬,以調整容器的性能
LinkedHashMap 類似于HashMap篷帅,但是便利它時,取得“鍵值對”的順序是其插入順序拴泌,或是最近最少使用的順序魏身。只比HashMap慢一點;而在迭代訪問時反而更快蚪腐,因為它使用鏈表維護內部的次序
TreeMap 基于紅黑樹的實現箭昵。查看“鍵”或“鍵值對”時,它們會被排序(由ComparableComparator決定)回季。TreeMap的特定在于家制,所得到的結果是經過排序的。TreeMap是唯一的帶有subMap()方法的Map泡一。它可以返回一個子樹
WeekHashMap 弱鍵映射颤殴,允許釋放映射所指向的對象;這是為解決某類特殊問題而設計的鼻忠。如果映射之外沒有引用指向某個“鍵”涵但,則此“鍵”可以被垃圾回收器回收
ConcurrentHashMap 一種線程安全的Map,它不涉及同步加鎖
IdentityHashMap 使用==代替equals()對“鍵”進行比較的散列映射。

4.對Map中使用的鍵的要求與對Set中的元素的要求一樣矮瘟。任何鍵都必須具有一個equals()方法瞳脓;如果鍵被用于散列Map,那么它必須還具有恰當的hashCode()方法澈侠;如果鍵被用于TreeMap劫侧,那么它必須實現Comparable
5.關聯數組中的基本方法是put()get()埋涧。keySet()方法返回一個由Map的鍵組成的Set板辽。可以直接通過values()方法獲取“值”棘催,該方法會產生一個包含Map中所有“值”的Collection劲弦,需要注意的是對該Collection的任何改動都會反映到與之相關聯的Map

二.SortedMap

1.使用SortedMapTreeMap是其現階段的唯一實現)醇坝,可以確币毓颍“鍵”處于排序狀態(tài)。
2.SortedMap接口中的一些特殊方法如下:

Method 功能描述
Comparator comparator() 返回當前Map使用的Comparator呼猪;或者返回null画畅,表示以自然方式排序
T firstKey() 返回Map中的第一個鍵
T lastKey() 返回Map中的最末一個鍵
SortedMap subMap(fromKey, toKey) 生成此Map的子集,范圍由fromKey(包含)到toKey(不包含)的鍵確定
SortedMap headMap(toKey) 生成此Map的子集宋距,由小于toKey的所有鍵值對確定
SortedMap tailMap(fromKey) 生成此Map的子集轴踱,由大于或等于fromMap的所有鍵值對組成
三.LinkedHashMap

1.為了提高速度,LinkedHashMap散列化所有的元素谚赎,但是在遍歷鍵值對時淫僻,卻又以元素的插入順序返回鍵值對。
2.可以在構造器中設定LinkedHashMap壶唤,使之采用基于訪問的最近最少使用算法雳灵。于是沒有被訪問過的元素酒會出現在隊列的最前面。對于需要定期清理元素以節(jié)省空間的程序來說闸盔,此功能使得程序很容易就能實現悯辙。

散列與散列碼

1.使用標準類庫中的類來作為HashMap的鍵沒有問題,因為它具備了鍵所需的全部性質迎吵。
2.當自己創(chuàng)建用作HashMap的鍵的類躲撰,有可能會忘記在其中放置必需的方法,而這是通常會犯的一個錯誤钓觉。
3.可能你會認為茴肥,只需編寫恰當的hashCode()方法的覆蓋版本即可。但是它仍然無法正常運行荡灾,除非你同時覆蓋equals()方法,它也是Object的一部分。HashMap使用equals()判斷當前的鍵是否與表中的相同批幌。
4.正確的equals()方法必須滿足的條件:
(1)自反性础锐。對任意xx.equals(x)一定返回true荧缘。
(2)對稱性皆警。對任意xy,如果y.equals(x)返回true截粗,則x.equals(y)一定返回true信姓。
(3)傳遞性。對任意x绸罗,y意推,z,如果有x.equals(y)返回true珊蟀,y.equals(z)返回true菊值,則x.equals(z)一定返回true
(4)一致性育灸。對任意xy腻窒,如果對象中用于等價比較的信息沒有改變,那么無論調用x.equals(y)多少次磅崭,返回的結果應該保持一致儿子,要么一直是true要么一直是false
(5)對任何不是nullx砸喻,x.equals(null)一定返回false柔逼。

一.理解hashCode()

1.使用散列的目的是:想要試用一個對象來查找另外一個對象。

二.為速度而散列

1.散列的價值在于速度:散列使得查詢得以快速進行恩够。
2.散列將鍵保存在某處卒落,以便能夠快速找到。存儲一組元素最快的數據結構是數組嗎所以使用它來表示鍵的信息蜂桶。
3.數組并不保存鍵本身儡毕。而是通過鍵對象生成一個數字,將其作為數組的下標扑媚。這個數字就是散列碼腰湾,由hashCode()方法生成。
4.為解決數組容量被固定的問題疆股,不同的鍵會產生相同的下標费坊。也就是說,可能會有沖突旬痹。因此附井,數組多大就不重要了讨越,任何鍵總能在數組中找到它的位置。
5.查詢一個值的過程首先就是計算散列碼永毅,然后使用散列碼查詢數組把跨。如果能夠沒有沖突,那就有了一個完美的散列函數沼死,但這只是特例着逐。通常。沖突由外部鏈接處理:數組并不直接保存值意蛀,而是保存值的list耸别。然后對list中的值使用equals()方法進行線性查詢。這部分的查詢自然會比較慢县钥,但是秀姐,如果散列函數好的話,數組的每個位置就只有較少的值魁蒜。因此囊扳,不會查詢整個list,而是快速地跳到數組的某個位置兜看,只對很少的元素進行比較锥咸。

三.覆蓋hashCode()

1.在使用HashMap的時候,你無法控制數組的下標值的產生细移。這個值依賴于具體的HashMap對象的容量搏予,而容量大改變與容器的充滿程度和負載因子有關。
2.設計hashCode()最重要的一個因素:無論何時弧轧,對同一個對象調用hashCode()都應該產生同樣的值雪侥。
3.不應該使hashCode()依賴于具有唯一性的對象信息,尤其是使用this的值精绎。因為這樣做無法生成一個新的鍵速缨,使之與put()中原始的鍵值對中的鍵相同。
4.hashCode()必須基于對象的內容生成散列碼代乃。散列碼不鄙視獨一無二的旬牲,但是通過hashCode()equals(),必須能夠完全確定對象的身份搁吓。
5.好的hashCode()應該產生分布均勻的散列碼原茅。如果散列碼都集中在一塊,那么HashMap或者HashSet在某些區(qū)域的負載會很重堕仔,這樣就不如分布均勻的散列函數快擂橘。
6.產生hashCode()的基本指導:
(1)給int變量result賦予某個非零值常量,例如17摩骨。
(2)為對象內每一個有意義的域f(即每個可以做equals()操作的域)計算出一個int散列碼c

域類型 計算
boolean c = (f ? 0 : 1)
byte通贞、char朗若、shortint c = (int)f
long c = (int) (f ^ (f >>> 32))
float c = Float.floatToBits(f)
double long l = Double.doubleToLongBits(f) c = (int) (l ^ l >>> 32)
Object滑频,其equals()調用這個域的equals() c = f.hashCode()
數組 對每個元素應用上面的規(guī)則

(3)合并計算得到的散列碼:
result = 37 * result + c;
(4)返回result捡偏。
(5)檢查hashCode()最后生成的結果唤冈,確保相同的對象有相同的散列碼峡迷。
7.compareTo()的創(chuàng)建方式:排序的規(guī)則首先按照實際類型排序,然后如果有名字的話你虹,按照name排序绘搞,最后安好創(chuàng)建的順序排序。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末傅物,一起剝皮案震驚了整個濱河市夯辖,隨后出現的幾起案子,更是在濱河造成了極大的恐慌董饰,老刑警劉巖蒿褂,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異卒暂,居然都是意外死亡啄栓,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門也祠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來昙楚,“玉大人,你說我怎么就攤上這事诈嘿】熬桑” “怎么了?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵奖亚,是天一觀的道長淳梦。 經常有香客問我,道長昔字,這世上最難降的妖魔是什么爆袍? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮李滴,結果婚禮上市埋,老公的妹妹穿的比我還像新娘嫂伞。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布策泣。 她就那樣靜靜地躺著,像睡著了一般洪囤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上闲先,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天,我揣著相機與錄音无蜂,去河邊找鬼伺糠。 笑死,一個胖子當著我的面吹牛斥季,可吹牛的內容都是我干的训桶。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼酣倾,長吁一口氣:“原來是場噩夢啊……” “哼舵揭!你這毒婦竟也來了?” 一聲冷哼從身側響起躁锡,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤午绳,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后映之,有當地人在樹林里發(fā)現了一具尸體拦焚,經...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年杠输,在試婚紗的時候發(fā)現自己被綠了赎败。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡抬伺,死狀恐怖螟够,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情峡钓,我是刑警寧澤妓笙,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站能岩,受9級特大地震影響寞宫,放射性物質發(fā)生泄漏。R本人自食惡果不足惜拉鹃,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一辈赋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧膏燕,春花似錦钥屈、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至近忙,卻和暖如春竭业,著一層夾襖步出監(jiān)牢的瞬間智润,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工未辆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留窟绷,地道東北人。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓咐柜,卻偏偏與公主長得像兼蜈,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子炕桨,可洞房花燭夜當晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內容

  • 本文出自 Eddy Wiki 饭尝,轉載請注明出處:http://eddy.wiki/interview-java.h...
    eddy_wiki閱讀 1,166評論 0 16
  • 一、基本數據類型 注釋 單行注釋:// 區(qū)域注釋:/* */ 文檔注釋:/** */ 數值 對于byte類型而言...
    龍貓小爺閱讀 4,268評論 0 16
  • 1. Java基礎部分 基礎部分的順序:基本語法实撒,類相關的語法姊途,內部類的語法,繼承相關的語法知态,異常的語法捷兰,線程的語...
    子非魚_t_閱讀 31,664評論 18 399
  • Java8張圖 11、字符串不變性 12负敏、equals()方法贡茅、hashCode()方法的區(qū)別 13、...
    Miley_MOJIE閱讀 3,709評論 0 11
  • 附記南遷得失 或問南遷得失何如其做?予應之曰:當自成逾秦入晉顶考,勢已破竹,惟南遷一策妖泄,或可稍延歲月驹沿,而光時亨以為邪說,其...
    隴右雷柯柯閱讀 194評論 0 1