标签:als 工作 val 指针 涵盖 lsp method put call
在JDK8中Map接口提供了一些新的便利的方法。因为在本文中我所提到的所有Map方法都是以默认值方法的方式实现的,所以现有的Map接口的实现可以直接拥有这些在默认值方法中定义的默认行为,而不需要新增一行代码。本文涵盖的JDK8中引进的Map方法有:getOrDefault(Object,V),putIfAbsent(K,V),remove(Object,Object),replace(K,V),和 replace(K,V,V)。
我将使用如下代码所示的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中符合提供的键的值,否则在没有找到提供的键的匹配项的时候返回一个“默认值”。
下一段代码列举对比了如何在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)在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)方法,只有在提供的键和值都匹配的时候才会删除该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”方法中的第一个方法只有在指定的键已经存在并且有与之相关的映射值时才会将指定的键映射到指定的值(新值),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方法在替换现存值方面有更窄的释义范围。当那个方法(上一个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" ); |
下面是一些根据本文得出的观察论点。
在本文涵盖的新增的Map方法都没有多少创造性或者重大特性更新,但是他们更便利,许多java开发者之前实现这些功能需要很多冗长的代码,为此而写他们自己的相似的方法,或者为此而使用一个第三方类库。JDK8把这些标准化的方法带给广大的java用户而不需要自定义实现或者第三方框架。因为是基于默认值方法的机制实现的,甚至那些已经存在一段时间的Map实现突然自动的就可以访问这些新增的方法而不需要做任何代码变更。
getOrDefault等jdk8为hash map 新增方法
标签:als 工作 val 指针 涵盖 lsp method put call
原文地址:http://www.cnblogs.com/vector11248/p/6789911.html