Java核心技術-映射

集是一個集合,它可以快速地查找現(xiàn)有的元素廊佩。但是囚聚,要查看一個元素,需要有要查找元素的精確副本标锄。這不是一種非常通用的查找方式。通常茁计,我們知道某些鍵的信息料皇,并想要查找與之對應的元素。映射(map)數(shù)據(jù)結構就是為此設計的星压。映射用來存放鍵/值對践剂。如果提供了鍵,就能夠查找到值娜膘。

基本映射操作

Java類庫為映射提供了兩個通用的實現(xiàn):HashMap和TreeMap逊脯。這兩個類都實現(xiàn)了Map接口。

散列映射對鍵進行散列竣贪,樹映射用鍵的整體順序?qū)υ剡M行排序军洼,并將其組織成搜索樹。散列或比較函數(shù)職能作用于鍵演怎。于鍵關聯(lián)的值不能進行散列或比較匕争。

散列稍微快一些,如果不需要按照排序順序訪問鍵爷耀,就最好選擇散列甘桑。

下列代碼將為存儲的員工信息建立一個散列映射:

Map<String, Employee> staff = new HashMap<>(); // HashMap implements Map
Employee harry = new Employee("Harry Hacker");
staff.put("987-98-9996", harry);

每當往映射中添加對象時,必須同時提供一個鍵。在這里跑杭,鍵是一個字符串铆帽,對應的值是Employee對象。

要想檢索一個對象德谅,必須使用(因而锄贼,必須記住)一個鍵女阀。

String id = "987-98-9996";

e = staff.get(id);

如果在映射中沒有與定鍵對應的消息宅荤,get將返回null。null返回值可能并不方便浸策。有時可以有一個好的默認值冯键,用作為映射中不存在的鍵。然后使用getOrDefault方法庸汗。

Map<String, Integer> scores = ...;

int score = scores.get(id,0); // Gets 0 if the id is not present

鍵必須是唯一的惫确。不能對同一個鍵存放兩個值。如果對同一個鍵兩次調(diào)用put方法蚯舱,第二個值就會取代第一個值改化。實際上,put將返回用這個鍵參數(shù)存儲的上一個值枉昏。

remove方法用于從映射中刪除給定鍵對應的元素陈肛。size方法用于返回映射中的元素數(shù)。

要迭代處理映射的鍵和值兄裂,最容易的方法是使用forEach方法句旱。

更新映射項

處理映射時的一個難點就是更新映射項。正常情況下晰奖,可以得到與一個鍵關聯(lián)的原值谈撒,完成更新,再放回更新后的值匾南。不過啃匿,必須考慮一個特殊情況,即鍵第一次出現(xiàn)蛆楞。下面來看一個例子溯乒,使用一個映射統(tǒng)計一個單詞再文件中出現(xiàn)的頻度‰叮看到單詞(word)時橙数,我們將計數(shù)器增1,如下所示:

counts.put(word, counts.get(word) + 1)

這是可以的帅戒,不過一種情況除外:就是第一次看到word時灯帮。在這種情況下崖技,get會返回null,因此會出現(xiàn)NullPointerException異常钟哥。

作為一個簡單的補救迎献,可以使用getOrDefault方法:

counts.put(word, counts.getOrDefault(word, 0) + 1);

另一個方法是首先調(diào)用putIfAbsent方法。只有當鍵原先存在時才會放入一個值腻贰。

counts.putInfAbsent(word, 0 );

counts.put(word,counts.get(word) + 1);

不過還可以做得更好吁恍。merge方法可以簡化這個常見的操作。如果鍵原先不存在播演,下面的調(diào)用:

counts.merge(word, 1,Integer::sum);

將把word與1關聯(lián)冀瓦,否則使用Integer::sum函數(shù)組合原值和1(也就是將原值與1求和)。

映射視圖

集合框架不認為映射本身是一個集合写烤。(其他數(shù)據(jù)結構框架認為映射是一個鍵/值對集合翼闽,或者是由鍵索引的值集合。)

弱散列映射

設計WeakHashMap類是為了解決一個有趣的問題洲炊。如果有一個值感局,對應的鍵已經(jīng)不再使用了,將會出現(xiàn)什么情況呢暂衡?

首先询微,垃圾回收器跟蹤活動的對象。只要映射對象是活動的狂巢,其中的所有桶也是活動的撑毛,它們不能被回收。

WeakHashMap使用弱引用(weak references)保存鍵隧膘。WeakReference對象將引用保存到另外一個對象中代态,在這里,就是散列鍵疹吃。對于這種類型的對象,垃圾回收器用一種特有的方式進行處理西雀。通常萨驶,如果垃圾回收器發(fā)現(xiàn)某個特定的對象已經(jīng)沒有他人引用了,就將其回收艇肴。然而腔呜,如果某個對象只能由WeakReference引用,垃圾回收器仍然回收它再悼,但要將引用這個對象的弱引用放入隊列中核畴。WeakHashMap將周期性地檢查隊列,以便找出新添加地弱引用冲九。一個弱引用進入隊列意味著這個鍵不再被他人使用谤草,并且已經(jīng)被收集起來跟束。于是,WeakHashMap將刪除對應的條目丑孩。

鏈接散列集與映射

鏈接散列映射將用訪問順序冀宴,而不是插入順序,對映射條目進行迭代温学。每次調(diào)用get或put略贮,受到影響的條目將從當前的位置刪除,并放到條目鏈表的尾部(只有條目在鏈表中的位置會受影響仗岖,而散列表中的桶不會受影響逃延。一個條目總位于與鍵散列碼對應的桶中)。

訪問順序?qū)τ趯崿F(xiàn)高速緩存的“最近最少使用”原則十分重要轧拄。

枚舉集與映射

EnumSet是一個枚舉類型元素集的高效實現(xiàn)揽祥。由于枚舉類型只有有限個實例,所以EnumSet內(nèi)部用位序列實現(xiàn)紧帕。如果對應的值在集中盔然,則相應的位被置為1。

EnumMap是一個鍵類型為枚舉類型的映射是嗜。他可以直接且高效地用一個值數(shù)組實現(xiàn)愈案。

標識散列映射

類IdentityHashMap有特殊的作用。在這個類中鹅搪,鍵的散列值不是用hashCode函數(shù)計算的站绪,而是用System.identityHashCode方法計算的。這是Object.hashCode方法根據(jù)對象的內(nèi)存地址類計算散列碼所使用的方式丽柿。而且恢准,在對兩個對象進行比較時,IdentityHashMap類使用==甫题,而不是用equals馁筐。

也就是說,不同的鍵對象坠非,即使內(nèi)容相同敏沉,也被視為是不同的對象。在實現(xiàn)對象遍歷算法(如對象串行化)時炎码,這個類非常有用盟迟,可以用來跟蹤每個對象的遍歷狀況。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末潦闲,一起剝皮案震驚了整個濱河市攒菠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌歉闰,老刑警劉巖辖众,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件卓起,死亡現(xiàn)場離奇詭異,居然都是意外死亡赵辕,警方通過查閱死者的電腦和手機既绩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來还惠,“玉大人饲握,你說我怎么就攤上這事〔霞” “怎么了救欧?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長锣光。 經(jīng)常有香客問我笆怠,道長,這世上最難降的妖魔是什么誊爹? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任蹬刷,我火速辦了婚禮,結果婚禮上频丘,老公的妹妹穿的比我還像新娘办成。我一直安慰自己,他們只是感情好搂漠,可當我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布迂卢。 她就那樣靜靜地躺著,像睡著了一般桐汤。 火紅的嫁衣襯著肌膚如雪而克。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天怔毛,我揣著相機與錄音员萍,去河邊找鬼。 笑死拣度,一個胖子當著我的面吹牛充活,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蜡娶,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼映穗!你這毒婦竟也來了窖张?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蚁滋,失蹤者是張志新(化名)和其女友劉穎宿接,沒想到半個月后赘淮,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡睦霎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年梢卸,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片副女。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡蛤高,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出碑幅,到底是詐尸還是另有隱情戴陡,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布沟涨,位于F島的核電站恤批,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏裹赴。R本人自食惡果不足惜喜庞,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望棋返。 院中可真熱鬧延都,春花似錦、人聲如沸懊昨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽酵颁。三九已至嫉你,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間躏惋,已是汗流浹背幽污。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留簿姨,地道東北人距误。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像扁位,于是被迫代替她去往敵國和親准潭。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內(nèi)容

  • Java集合框架 Java中封裝了許多常用的數(shù)據(jù)結構域仇,稱為集合框架刑然,可以有效組織數(shù)據(jù),提高程序性能暇务。最初Java只...
    Steven1997閱讀 935評論 0 2
  • 一泼掠、迭代器 iterator是一個或者實現(xiàn)了Iterator,或者實現(xiàn)ListIterator接口的對象怔软,可以通過...
    pinnuli閱讀 234評論 0 0
  • 概要 這一章,我們對WeakHashMap進行學習择镇。 我們先對WeakHashMap有個整體認識挡逼,然后再學習它的源...
    廢棄的root閱讀 543評論 0 0
  • 官網(wǎng) 中文版本 好的網(wǎng)站 Content-type: text/htmlBASH Section: User ...
    不排版閱讀 4,401評論 0 5
  • 一道閃電劃破天空,暴雨連同海水打在她臉上腻豌,她想拼命醒來家坎,卻仿佛被抽干了力氣,睜不開雙眼饲梭。盡管如此乘盖,胳膊卻被...
    miss七哥閱讀 262評論 0 1