getOrDefault等jdk8为hash map 新增方法

在JDK8中Map接口提供了一些新的便利的方法。因为在本文中我所提到的所有Map方法都是以默认值方法的方式实现的,所以现有的Map接口的实现可以直接拥有这些在默认值方法中定义的默认行为,而不需要新增一行代码。本文涵盖的JDK8中引进的Map方法有:getOrDefault(Object,V)putIfAbsent(K,V),remove(Object,Object)replace(K,V),和 replace(K,V,V)

Map范例

我将使用如下代码所示的Map声明和初始化来贯穿整篇博文中的示例。字段stateAndCapitals是类级别的静态字段。为了阅读清晰和更简单的示范一些JDK8中新的Map默认值方法,我有意的让stateAndCapitals字段只包含了美国50个洲的一个小子集。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

private final static Map statesAndCapitals;

static

{

      statesAndCapitals = new HashMap<>();

      statesAndCapitals.put("Alaska", "Anchorage");

      statesAndCapitals.put("California", "Sacramento");

      statesAndCapitals.put("Colorado", "Denver");

      statesAndCapitals.put("Florida", "Tallahassee");

      statesAndCapitals.put("Nevada", "Las Vegas");

      statesAndCapitals.put("New Mexico", "Sante Fe");

      statesAndCapitals.put("Utah", "Salt Lake City");

      statesAndCapitals.put("Wyoming", "Cheyenne");

}

Map.getOrDefault(Object, V)

Map的新方法getOrDefault(Object,V)允许调用者在代码语句中规定获得在map中符合提供的键的值,否则在没有找到提供的键的匹配项的时候返回一个“默认值”。

下一段代码列举对比了如何在JDK8之前检查一个map中匹配提供键的值是否找到,没找到匹配项就使用一个默认值是如何实现的,并且现在在JDK8中是如何实现的。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

/*

 * 示范Map.getOrDefault方法并和JDK8之前的实现方法做对比。JDK8

 * 中新增的Map.getOrDefault方法相比于传统的实现方法,所用的代码行数更少

 * 并且允许用一个final类型的变量来接收返回值。

 */

// JDK8之前的实现方法

String capitalGeorgia = statesAndCapitals.get("Georgia");

if (capitalGeorgia == null)

{

   capitalGeorgia = "Unknown";

}

// JDK8的实现方法

final String capitalWisconsin = statesAndCapitals.getOrDefault("Wisconsin", "Unknown");

Apache Commons包的DefaultedMap类提供了和新的Map.getOrDefault(Object, V)方法类似的功能。Groovy GDK中为Groovy包含了一个类似的方法,Map.get(Object,Object),但是这个方法的行为有一点不同,因为它不仅仅在“键”没找到的时候返回提供的默认值,而且还会将键和默认值增加到调用的map中。

Map.putIfAbsent(K,V)

Map的新方法putIfAbsent(K,V)在javadoc中已经公布了它的默认实现的等价代码:


1

2

3

4

5

V v = map.get(key);

if (v == null)

   v = map.put(key, value);

return v;

这在另一段对比JDK8之前的实现方法和JDK8的实现方法的代码示例中得到了证明。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

/*

 * 示范Map.putIfAbsent方法并和JDK8之前的实现方法做对比。JDK8

 * 中新增的Map.putIfAbsent方法相比于传统的实现方法,所用的代码行数更少

 * 并且允许用一个final类型的变量来接收返回值。

 */

// JDK8之前的实现方式

String capitalMississippi = statesAndCapitals.get("Mississippi");

if (capitalMississippi == null){

   capitalMississippi = statesAndCapitals.put("Mississippi", "Jackson");

}

// JDK8的实现方式

final String capitalNewYork = statesAndCapitals.putIfAbsent("New York", "Albany");

在putIfAbsent方法增加之前,java方面的替代解决方案在StackOverflow上的java map.get(key)–automatically do put(key) and return if key doesn’t exist?帖子讨论过。在JDK8之前这没有任何意义,ConcurrentMap接口(继承自Map)已经提供了一个putIfabsent(K,V)方法。

Map.remove(Object.Object)

Map的新方法remove(Object,Object)超越了长期有效的Map.remove(Object)方法,只有在提供的键和值都匹配的时候才会删除该map项(之前的有效版本只是查找“键”的匹配来删除)。

该方法的javadoc的注释解释了默认值方法的具体实现在JDK8之前的java代码是如何工作的:
对于文中的map,该默认值实现是等价于新方法的:


1

2

3

4

5

6

if (map.containsKey(key) && Objects.equals(map.get(key), value)) {

   map.remove(key);

   return true;

} else {

   return false;

}

下面这段代码列举展示的是新实现方法和JDK8之前的实现方法的一个具体比较。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

/*

 * 示范Map.remove(Object,Object)方法并和JDK8之前的实现方法做对比。JDK8

 * 中新增的Map.remove(Object,Object)方法相比于传统的实现方法,所用的代码行数更少

 * 并且允许用一个final类型的变量来接收返回值。

 */

// JDK8之前的实现方式

 boolean removed = false;

 if (   statesAndCapitals.containsKey("New Mexico")

    && Objects.equals(statesAndCapitals.get("New Mexico"), "Sante Fe")) {

    statesAndCapitals.remove("New Mexico", "Sante Fe");

    removed = true;

}

// JDK8的实现方式

final boolean removedJdk8 = statesAndCapitals.remove("California", "Sacramento");

Map.replace(K,V)

两个新增的Map “replace”方法中的第一个方法只有在指定的键已经存在并且有与之相关的映射值时才会将指定的键映射到指定的值(新值),javadoc的注释解释了该默认值方法的实现的等价java代码:

对于文中的map,该默认值实现是等价于新方法的:


1

2

3

4

5

if (map.containsKey(key)) {

   return map.put(key, value);

} else {

   return null;

}

下面展示的是新方法和JDK8之前的方法比较:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

/*

 * 示范Map.replace(K, V)方法并和JDK8之前的实现方法做对比。JDK8

 * 中新增的Map.replace(K, V)方法相比于传统的实现方法,所用的代码行数更少

 * 并且允许用一个final类型的变量来接收返回值。

 */

// JDK8之前的实现方式

String replacedCapitalCity;

if (statesAndCapitals.containsKey("Alaska"))  {

   replacedCapitalCity = statesAndCapitals.put("Alaska", "Juneau");

}

// JDK8的实现方式

final String replacedJdk8City = statesAndCapitals.replace("Alaska", "Juneau");

Map.replace(K,V,V)

第二的新增的Map replace方法在替换现存值方面有更窄的释义范围。当那个方法(上一个replace方法)只是涵盖指定的键在映射中有任意一个有效的值的替换处理,而这个“replace”方法接受一个额外的(第三个)参数,只有在指定的键和值都匹配的情况下才会替换。
javadoc注释说明了该默认值方法的实现:


1

2

3

4

5

6

if (map.containsKey(key) && Objects.equals(map.get(key), value)) {

    map.put(key, newValue);

    return true;

} else {

    return false;

}

下面这段代码列举展示的是新实现方法和JDK8之前的实现方法的一个具体比较。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

/*

 * 示范Map.replace(K, V, V)方法并和JDK8之前的实现方法做对比。JDK8

 * 中新增的Map.replace(K, V, V)方法相比于传统的实现方法,所用的代码行数更少

 * 并且允许用一个final类型的变量来接收返回值。

 */

// JDK8之前的实现方式

 boolean replaced = false;

 if (   statesAndCapitals.containsKey("Nevada")

    && Objects.equals(statesAndCapitals.get("Nevada"), "Las Vegas")) {

     statesAndCapitals.put("Nevada", "Carson City");

     replaced = true;

 }

// JDK8的实现方式

final boolean replacedJdk8 = statesAndCapitals.replace("Nevada", "Las Vegas", "Carson City");

观察与结论

下面是一些根据本文得出的观察论点。

  • 对与这些JDK8中Map的新增方法,javadoc方法是很有用的,特别是在用JDK8之前的代码描述新方法的行为时。我是在JDK 8 javadoc-based API documentation的基础上更宽泛的讨论这些方法的javadoc文档。
  • 由这些方法的javadoc注释中指出的等价java代码可以得出,这些方法在访问map的键和值之前通常不会做非空检查。因此,在使用这些方法和javadoc注释中的等价java时会引发同样的空指针问题。实际上,javadoc注释通常会根据一些允许键和值为空或不为空的Map具体实现会引发空指针和其他问题的可能性而提出警告
  • 在本文中讨论的新增的Map方法都是“默认值方法”,意味着Map的具体实现会自动“继承”这些(默认值)实现
  • 在本文中讨论的新增的Map方法把代码的干净简明考虑在内。在我大多数的例子中,他们允许客户端代码从多行状态相连的语句转换成单行语句并一劳永逸的(把返回值)赋值给一个本地变量。

在本文涵盖的新增的Map方法都没有多少创造性或者重大特性更新,但是他们更便利,许多java开发者之前实现这些功能需要很多冗长的代码,为此而写他们自己的相似的方法,或者为此而使用一个第三方类库。JDK8把这些标准化的方法带给广大的java用户而不需要自定义实现或者第三方框架。因为是基于默认值方法的机制实现的,甚至那些已经存在一段时间的Map实现突然自动的就可以访问这些新增的方法而不需要做任何代码变更。

时间: 2024-08-19 05:16:36

getOrDefault等jdk8为hash map 新增方法的相关文章

Java 8之Map新增方法&lt;转&gt;

在Java 8中的Map.Entry接口中增加了comparingByKey, comparingByValue方法,它们都返回Comparator<Map.Entry<K,V>>, Comparator是一个函数接口,主要是方便Lambda表达式的使用. 在Java 8中的Map接口增加了一些default方法,提升了对key, value操作的便利性.下面是基本数据的定义,通过这些数据说明新增的一些方法. 1234 Map<Integer, String> map

[LeetCode] Repeated DNA Sequences hash map

All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for example: "ACGAATTCCG". When studying DNA, it is sometimes useful to identify repeated sequences within the DNA. Write a function to find all the 10-letter-long seq

Perl hash map操作,定义,插入,删除,hash函数

#!/usr/bin/perl -w ######################################################################### # File Name: test3.pl ######################################################################### print "hash map\n"; my %some_hash = ("key1", 1

ES5 新增方法概述

ES5 新增方法概述 ES5 中给我们创建了一些方法,可以很方便的操作数组或者字符串,这些方法主要包括: 数组方法 字符串方法 对象方法 数组方法 迭代(遍历)方法:forEach().map().filter().some().every() array.forEach(function(currentValue,index,arr)) currentValue:数组当前项的值 index:数组当前项的索引 arr:数组对象本身 相似于 map() return 不会中止循环 rray.fil

hdu1381 Crazy Search(hash map)

题目意思: 给出一个字符串和字串的长度,求出该字符串的所有给定长度的字串的个数(不相同). 题目分析: 此题为简单的字符串哈hash map问题,可以直接调用STL里的map类.map<string,int> snum; AC代码: #include<iostream> #include<string> #include<map> using namespace std; int main() { int t,n,nc; cin>>t; whil

HTML5的新增方法

json的新增方法: parse()   将JSON转换为字符串:必须是严格的JSON格式: 用法 : var s = {"name":"name"}; JSON.parse(s) stringigy()将字符串转换为JSON格式 用法:同上: parse()方法与eval()的区别: eval()可以解析任何数据:而parse()只能解析严格模式的JSON数据: 新增选择器: querySelector() 类似于JQ里面的$:但只能选择一组元素里面的第一个元素:

velocity两种map遍历方法

velocity 中list遍历比较简单,那么map遍历呢,这里举出两种velocity Map 遍历方法. 两种velocity遍历map java代码: soft属性:数量num,名字name Soft soft = new Soft("3","爱奇艺app"); softTypeMap{1,soft} 前端代码: 1: #foreach($item in $!softTypeMap.entrySet()) <option value="$!{i

重载hash与isEqual:方法

前言 NSObject 自带了hash与isEqual:方法,服务于具有hash表结构的数据结构.NSObject自带的hash函数相当于hash表中的f(key)函数中的key,这“唯一”的key需要用户自己产生,至于用什么算法由用户自己决定. 准备 // // Model.h // Hash // // Created by YouXianMing on 16/4/15. // Copyright © 2016年 YouXianMing. All rights reserved. // #i

Java之map使用方法

1 package basic; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 6 //map使用方法 7 public class MapDemo { 8 9 public static void main(String[] args) { 10 // map实例化 11 Map<String, Integer> maps = new HashMap<>(); 12 13 // 添加元素 14 maps.put(&