Map 是我们经常使用的数据结构接口,它的子类 HashMap、ConcurrentHashMap 也是我们使用比力频繁的集合。
相识了 Map 接口中的方法,也就相称于知道了其子类中的可用方法,管它是不是并发类。
自 JDK 8 起,Map 引入了一些新的方法,显著提升了对数据操作的便利性和代码可读性。随着 JDK 的发展,最新的版本已更新到 21,这些在 JDK 8 中新增的方法虽已不算 “新”,但如果你还未熟练掌握,可就真的 “落后” 了!
这几个方法实在之前说过,为什么这次再次说,因为重要的事情讲三遍,记不住就再来一遍。
HashMap 中非常好用又经常被忽略的方法
1.getOrDefault
用途:根据指定键获取值,如果键不存在,则返回默认值。
示例代码:- java
- Map<String, String> map = new HashMap<>(4);
- map.put("123", "123");
- String key = "key";
- String defaultValue = "defaultValue";
- // 传统写法
- String oldValue = defaultValue;
- if (map.containsKey(key)) {
- oldValue = map.get(key);
- }
- // 输出:defaultValue = defaultValue,realValue=null
- System.out.println("defaultValue = " + oldValue + ",realValue=" + map.get(key));
- // 优雅写法
- String newValue = map.getOrDefault(key, defaultValue);
- // 输出:defaultValue = defaultValue,realValue=null
- System.out.println("defaultValue = " + newValue + ",realValue=" + map.get(key));
复制代码 优点:减少了对 containsKey 的显式调用,简化了代码逻辑。
2.forEach
用途:更方便地遍历 Map 中的键值对。
示例代码:- java
- Map<String, String> map = new HashMap<>(4);
- map.put("111", "111");
- // 传统写法
- for (Map.Entry<String, String> entry : map.entrySet()) {
- System.out.printf("key = %s, value = %s%n", entry.getKey(), entry.getValue());
- }
- // 简洁写法
- map.forEach((key, value) -> System.out.printf("key = %s, value = %s%n", key, value));
复制代码 优点:代码更简洁,直接通过 Lambda 表达式操作。
3.merge
用途:用于归并键值对,根据指定的逻辑更新或插入值。
工作原理:如果键存在,应用归并函数计算新值,并更新到 Map 中。如果键不存在,将键值对直接插入到 Map 中。
示例代码:- java
- Map<String, Integer> map = new HashMap<>(8);
- List<String> list = Arrays.asList("a", "b", "c");
- // 传统写法
- for (String item : list) {
- if (map.containsKey(item)) {
- map.put(item, map.get(item) + 1);
- } else {
- map.put(item, 1);
- }
- }
- System.out.println(map); // 输出:{a=1, b=1, c=1}
- Map<String, Integer> map1 = new HashMap<>(8);
- // 简洁写法
- for (String item : list) {
- map1.merge(item, 1, Integer::sum);
- }
- System.out.println(map1); // 输出:{a=1, b=1, c=1}
复制代码 优点:用一行代码即可实现计数逻辑,避免显示查抄,简化复杂流程。
4.putIfAbsent
用途:仅在键不存在或值为 null 时,插入新的键值对。
示例代码:- java
- Map<String, Integer> map = new HashMap<>(4);
- map.put("Jim", 5);
- map.put("Lily", 10);
- // 传统写法
- if (!map.containsKey("Lily")) {
- map.put("Lily", 10);
- }
- // 简洁写法
- map.putIfAbsent("Jim", 5);
- System.out.println(map); // 输出:{Lily=10, Jim=5}
复制代码 优点:避免重复查抄逻辑,使代码更加直观。
5.compute
用途:通过函数对键对应的值举行动态计算。
典型应用场景:计数或根据复杂逻辑更新值。
示例代码:- java
- Map<String, Integer> map = new HashMap<>(8);
- List<String> list = Arrays.asList("a", "b", "c");
- // 传统写法
- for (String item : list) {
- if (map.containsKey(item)) {
- map.put(item, map.get(item) + 1);
- } else {
- map.put(item, 1);
- }
- }
- System.out.println(map); // 输出:{a=1, b=1, c=1}
- Map<String, Integer> map1 = new HashMap<>(8);
- // 优雅写法
- for (String item : list) {
- map1.compute(item, (k, v) -> (v == null)? 1 : v + 1);
- }
- System.out.println(map1); // 输出:{a=1, b=1, c=1}
复制代码 优点:逻辑内聚,避免外部重复判断。
6.computeIfAbsent
用途:当键不存在时,才通过计算生成值并插入。
示例代码:
java
Map map = new ConcurrentHashMap(16);
map.put(0, 1);
map.put(1, 1);
// 传统写法,先显式查抄键是否存在,然后举行插入或计算。
if (!map.containsKey(5)) {
map.put(5, Integer.sum(map.get(0), map.get(1)));
}
System.out.println(map); // 输出:{0=1, 1=1, 5=2}
// 优雅写法
map.computeIfAbsent(3, i -> Integer.sum(map.get(0), map.get(1)));
System.out.println(map); // 输出:{0=1, 1=1, 3=2, 5=2}
优点:避免显式查抄键是否存在,逻辑更清晰。
7.computeIfPresent
用途:仅当键存在时,才通过计算更新值。
示例代码:- java
- Map<String, Integer> map = new HashMap<>(4);
- map.put("a", 10);
- map.put("b", 5);
- // 传统写法:显式判断键是否存在
- if (map.containsKey("a")) {
- Integer newScore = map.get("a") + 10;
- map.put("a", newScore);
- }
- System.out.println(map); // 输出:{a=20, b=5}
- // 简洁写法:使用 computeIfPresent
- map.computeIfPresent("b", (k, v) -> v + 10);
- System.out.println(map); // 输出:{a=20, b=15}
复制代码 优点:自动查抄键是否存在并举行更新,逻辑简洁且代码量减少。
注意:Absent 意为缺席的,present 意为目前的。computeIfAbsent 是键不存在时做处理,computeIfPresent 是键存在时做处理,两个刚好相反。
8. replace
用途:键存在时,更新值;键不存在时,不做任何操作。
示例代码:- java
- Map<String, String> map = new HashMap<>();
- map.put("key", "oldValue");
- // 传统写法:检查键是否存在,然后更新
- if (map.containsKey("key")) {
- map.put("key", "newValue");
- }
- System.out.println(map); // 输出:{key=newValue}
- // 使用 replace 方法直接更新
- map.replace("key", "newValue11");
- System.out.println(map); // 输出:{key=newValue11}
复制代码 优点:使用 replace 方法的优势在于代码更加简洁,且自动处理键存在时的更新,如果键不存在,则不执行任何操作,避免了不须要的显式键查抄。
末了总结
通过掌握这些方法,我们可以在以了局景中显著进步开发效率:
避免不须要的覆盖 (putIfAbsent、replace)
提供默认值以简化逻辑 (getOrDefault)
灵活处理键值更新 (merge、compute、computeIfPresent、computeIfAbsent)
高效遍历或批量操作 (forEach)
这些方法固然使用频率不如底子操作,但在特定需求下往往能提供更清晰、简洁的代码逻辑。希望大家在实际开发中多加使用,写出更优雅的代码!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |