共计 3460 个字符,预计需要花费 9 分钟才能阅读完成。
背景
大家好,我是栈长。
前些天,栈长给大家分享了 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 进行去重了,输入后果:
{李四 =user2, 张三 =user1, 王五 =user8, 赵六 =user6}
尽管能去重了,然而 HashMap 中的 Key 和 Value 值却颠倒了,所以须要第二次收集。
第二次收集:
当初的 Key 是之前的 Value,所以须要再互相换过来,输入后果:
{user1= 张三, user2= 李四, user8= 王五, user6= 赵六}
这个办法比拟绕,尽管能一行代码搞定,但代码很冗余,不是很优雅, 最重要的是这两次的收集过程会创立两次新 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 开发手册(嵩山版)》最新公布,速速下载!
感觉不错,别忘了顺手点赞 + 转发哦!