面試官:怎麼刪除 HashMap 中的重複元素?第 3 種實現思路,99% 的人不會!
背景
大家好,我是棧長。
前些天,棧長給大家分享了 3 篇實用的文章:
帶了一個 3 年的開發,不會迴圈刪除 List 中的元素,我簡直崩潰!! 面試官:怎麼去除 List 中的重複元素?我一行程式碼搞定,趕緊拿去用! 面試官:怎麼刪除 HashMap 中的元素?我一行程式碼搞定,趕緊拿去用!
List 和 Map 元素的刪除、去重,這些都是工作中經常遇到的問題,一些基礎程式設計師可能會走一些彎路,所以棧長輸出了三篇,希望對大家有用,其中一些程式設計技巧很多老程式設計師也沒用過,所以,技術真的是學無止境。
今天棧長帶來集合的刪除及去重系列的最後一篇,如何刪除 HashMap 中的重複元素,即怎麼根據 Value 去重,去除 HashMap 中 Value 重複的元素,這也是面試官可能會問到的。
為什麼不是根據 Key 去重?
大家都知道,HashMap 的 key 是不會重複的,如果有重複就會用新值覆蓋舊值。
當我們向一個 HashMap 中插入元素時,HashMap 會根據這個 key 的 equals 和 hashCode 方法進行判斷,如果兩個 key 的值用 equals 方法比較相同,且 key 的 hashCode 值也相同,那麼 HashMap 將認為這是同一個 key,後續插入相同 key 的鍵值對會將舊值替換為新值。
需要注意的是:
Java 中的基本資料型別和 String 等內建類,它們已經正確實現了 equals 和 hashCode 方法,可以直接用作 HashMap 的 key,而不會導致重複的 key 出現。
如果我們使用自定義類的物件作為 HashMap 的 key,需要保證這個類正確實現了 equals 和 hashCode 方法,否則可能會出現插入 "重複 key" 的情況,正常情況下,這是不符合規範和邏輯的。
HashMap 刪除重複元素方案
以下 HashMap 初始測試資料:
public Map<String, String> initMap = new HashMap<>() {{
put("user1", "張三");
put("user2", "李四");
put("user3", "張三");
put("user4", "李四");
put("user5", "王五");
put("user6", "趙六");
put("user7", "李四");
put("user8", "王五");
}};
本文所有完整示例原始碼已經上傳:
歡迎 Star 學習,後面 Java 示例都會在這上面提供!
1、新建立 Map 新增不重複元素
/**
* 新建立 Map 新增不重複元素
* @author: 棧長
* @from: 公眾號Java技術棧
*/
@Test
public void removeDuplicated1() {
Map<String, String> map = new HashMap<>();
initMap.forEach((k, v) -> {
if (!map.containsValue(v)) {
map.put(k, v);
}
});
System.out.println(map);
}
這種方法很原始,透過建立一個新 HashMap,新增元素前進行判斷,如果元素在新 HashMap 中不存在才進行新增。
2、新增 Set 再刪除重複元素
/**
* 新增 Set 再刪除重複元素
* @author: 棧長
* @from: 公眾號Java技術棧
*/
@Test
public void removeDuplicated2() {
Set<String> set = new HashSet<>();
Iterator<Map.Entry<String, String>> iterator = initMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, String> entry = iterator.next();
if (!set.add(entry.getValue())) {
iterator.remove();
}
}
System.out.println(initMap);
}
這種方法和第一種方法大同小異,透過建立一個 HashSet,然後遍歷 HashMap,因為 HashSet 是不允許重複元素的,所以,如果 HashSet 能新增元素說明元素沒有重複,否則說明元素重複了,然後刪除即可。
另外,HashSet、HashMap 的關係也是面試必問的,如果你近期準備面試跳槽,建議在Java面試庫小程式線上刷題,涵蓋 2000+ 道 Java 面試題,幾乎覆蓋了所有主流技術面試題。
3、使用 Stream 刪除重複元素
/**
* 使用 Stream 刪除重複元素
* @author: 棧長
* @from: 公眾號Java技術棧
*/
@Test
public void removeDuplicated3() {
Map<String, String> resultMap = initMap.entrySet().stream().collect(
Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey, (key1, key2) -> key1)
).entrySet().stream().collect(
Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey, (key1, key2) -> key1)
);
System.out.println(resultMap);
}
利用 Stream 的 collect 方法重新進行收集,這個方法也十分簡單,一行程式碼搞定,為了可讀性,文中程式碼進行了換行。Stream 基礎就不介紹了,Stream 系列我之前寫過一個專題了,不懂的關注公眾號Java技術棧,然後在公眾號 Java 教程選單中閱讀。
Collectors.toMap 方法返回的是一個Collector,它可以將元素累積到 Map 中,Map 的鍵和值將提供的對映函式應用到輸入元素的結果,如果對映的鍵包含重複項,則值對映函式會使用提供的 merge 函式進行結果合併。
Collectors.toMap 方法可以對 Key 進行去重合並,這也是為什麼進行了兩次 collect 收集的原因:
第一次收集:
把 Value 作為 Key,Key 作為 Value,這樣就能使用 Value 進行去重了,輸出結果:
{李四=user2, 張三=user1, 王五=user8, 趙六=user6}
雖然能去重了,但是 HashMap 中的 Key 和 Value 值卻顛倒了,所以需要第二次收集。
第二次收集:
現在的 Key 是之前的 Value,所以需要再相互換過來,輸出結果:
{user1=張三, user2=李四, user8=王五, user6=趙六}
這個方法比較繞,雖然能一行程式碼搞定,但程式碼很冗餘,不是很優雅,最重要的是這兩次的收集過程會建立兩次新 Map,相對比較耗記憶體。
總結
本文總結了 3 種刪除 HashMap 重複元素的方法:
新建立 Map 新增不重複元素 新增 Set 再刪除重複元素(推薦) 使用 Stream 刪除重複元素
實際開發過程中,可能會使用不同的遍歷方式,使用哪種刪除方案可以根據不同的遍歷方式進行選擇,但推薦使用 Set 方案,可以直接刪除 Map 中的重複元素,不會建立新的 HashMap。
另外,遍歷集合時需要重點考慮是否有多執行緒修改元素的場景,可能導致的併發修改異常,參考之前文章中介紹的方案,這裡不再撰述了。
本文所有完整示例原始碼已經上傳:
歡迎 Star 學習,後面 Java 示例都會在這上面提供!
你身邊還有誰不會刪除 HashMap 中的重複元素?把這篇文章發給他吧,讓大家少走彎路,少寫垃圾程式碼,共同進步。
你還知道哪些 HashMap 去重技巧?歡迎留言分享~
好了,今天的分享就到這裡了,後面棧長會分享更多好玩的 Java 技術和最新的技術資訊,關注公眾號Java技術棧第一時間推送,我也將主流 Java 面試題和參考答案都整理好了,大家可以在Java面試庫小程式進行刷題。
版權宣告: 本文系公眾號 "Java技術棧" 原創,轉載、引用本文內容請註明出處,抄襲、洗稿一律投訴侵權,後果自負,並保留追究其法律責任的權利。
End
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024923/viewspace-2939563/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 0928面試小節:刪除有序連結串列中的重複元素面試
- 面試官:Redis中大Key怎麼刪除?面試Redis
- (c語言實現)刪除有序連結串列中重複出現的元素C語言
- ES6刪除字串中重複的元素字串
- HashMap 之元素刪除HashMap
- JavaScript陣列刪除重複元素JavaScript陣列
- JavaScript 刪除陣列重複元素JavaScript陣列
- Remove Duplicate Letters 刪除重複元素REM
- 在ArrayList的迴圈中刪除元素,會不會出現問題?
- Python刪除列表元素的3種方法,你都會嗎?Python
- leetcode-刪除排序陣列中的重複項+移除元素LeetCode排序陣列
- 力扣-83. 刪除排序連結串列中的重複元素力扣排序
- 83. 刪除排序連結串列中的重複元素(JavaScript版)排序JavaScript
- leetcode-82:刪除排序連結串列中重複的元素-iiLeetCode排序
- 面試官問:為什麼HashMap底層樹化的元素是 8面試HashMap
- 面試官問:Kafka 會不會丟訊息?怎麼處理的?面試Kafka
- leetcode面試經典150-26. 刪除有序陣列中的重複項LeetCode面試陣列
- Python 中刪除列表元素的三種方法Python
- JavaScript 拼接多個陣列並刪除重複元素JavaScript陣列
- sqlserver中刪除重複資料SQLServer
- JavaScript刪除字串中重複字元JavaScript字串字元
- Oracle中刪除表中的重複資料Oracle
- mysql 刪除表中重複的資料MySql
- 刪除排序陣列中的重複項排序陣列
- VSCode刪除重複的空行VSCode
- MariaDB刪除重複記錄效能測試
- PostgreSQL刪除表中重複資料SQL
- 資料結構實驗之連結串列七:單連結串列中重複元素的刪除資料結構
- C# 批次刪除Excel中的重複行C#Excel
- 刪除有序陣列中的重複項 II陣列
- 刪除字串中的所有相鄰重複項字串
- mysql 刪除重複項MySql
- 刪除oracle重複值Oracle
- JavaScript 刪除重複字元JavaScript字元
- 刪除重複資料
- 答面試官問:怎麼實現介面冪等性面試
- 面試官:3 種快取更新策略是怎樣的?面試快取
- 刪除重複id的記錄