背景
大家好,我是堆疊長,
前些天,堆疊長給大家分享了 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", "王五");
}};
本文所有完整示例源代碼已經上傳:
https://github.com/javastacks/javastack
歡迎 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 進行去重了,輸出結果:
雖然能去重了,但是 HashMap 中的 Key 和 Value 值卻顛倒了,所以需要第二次收集,
第二次收集:
現在的 Key 是之前的 Value,所以需要再相互換過來,輸出結果:
這個方法比較繞,雖然能一行代碼搞定,但代碼很冗余,不是很優雅,最重要的是這兩次的收集程序會創建兩次新 Map,相對比較耗記憶體,
總結
本文總結了 3 種洗掉 HashMap 重復元素的方法:
- 新創建 Map 添加不重復元素
- 添加 Set 再洗掉重復元素(推薦)
- 使用 Stream 洗掉重復元素
實際開發程序中,可能會使用不同的遍歷方式,使用哪種洗掉方案可以根據不同的遍歷方式進行選擇,但推薦使用 Set 方案,可以直接洗掉 Map 中的重復元素,不會創建新的 HashMap,
另外,遍歷集合時需要重點考慮是否有多執行緒修改元素的場景,可能導致的并發修改例外,參考之前文章中介紹的方案,這里不再撰述了,
本文所有完整示例源代碼已經上傳:
https://github.com/javastacks/javastack
歡迎 Star 學習,后面 Java 示例都會在這上面提供!
你身邊還有誰不會洗掉 HashMap 中的重復元素?把這篇文章發給他吧,讓大家少走彎路,少寫垃圾代碼,共同進步,
你還知道哪些 HashMap 去重技巧?歡迎留言分享~
好了,今天的分享就到這里了,后面堆疊長會分享更多好玩的 Java 技術和最新的技術資訊,關注公眾號Java技術堆疊第一時間推送,我也將主流 Java 面試題和參考答案都整理好了,大家可以在Java面試庫小程式進行刷題,
著作權宣告: 本文系公眾號 "Java技術堆疊" 原創,轉載、參考本文內容請注明出處,抄襲、洗稿一律投訴侵權,后果自負,并保留追究其法律責任的權利,
近期熱文推薦:
1.1,000+ 道 Java面試題及答案整理(2022最新版)
2.勁爆!Java 協程要來了,,,
3.Spring Boot 2.x 教程,太全了!
4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優雅的方式!!
5.《Java開發手冊(嵩山版)》最新發布,速速下載!
覺得不錯,別忘了隨手點贊+轉發哦!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/546776.html
標籤:Java
上一篇:一天吃透MySQL鎖面試八股文
下一篇:URule規則引擎
