use*_*188 12 java oracle concurrenthashmap java-8
我正在测试ConcurrentHashMapOracle的Java 8实现:
ConcurrentMap<String, String> concurrentMap = new ConcurrentHashMap<>();
String result = concurrentMap.computeIfAbsent("A", k -> "B");
System.out.println(result); // "B"
result = concurrentMap.putIfAbsent("AA", "BB");
System.out.println(result); // null
Run Code Online (Sandbox Code Playgroud)
实施要求:
默认实现等效于此映射的以下步骤,然后返回当前值,如果现在不存在则返回null:
Run Code Online (Sandbox Code Playgroud)if (map.get(key) == null) { V newValue = mappingFunction.apply(key); if (newValue != null) return map.putIfAbsent(key, newValue); }
它表示然后返回当前值,如果现在不存在则返回null.那不应该回来null吗?鉴于这putIfAbsent也正在回归null.
我在这里错过了什么?
Hol*_*ger 16
代码示例ConcurrentMap.computeIfAbsent不反映实际意图,很可能是由非直观行为引起的错误putIfAbsent,而实现服从记录的意图.这已在JDK-8174087中报告
并在Java 9中修复
注意合同Map.computeIfAbsent是
实施要求:
默认实现等效于此映射的以下步骤,然后返回当前值,如果现在不存在则返回null:
Run Code Online (Sandbox Code Playgroud)if (map.get(key) == null) { V newValue = mappingFunction.apply(key); if (newValue != null) map.put(key, newValue); }
省略return声明.但是清楚地说
返回:
与指定键关联的当前(现有或已计算)值,如果计算值为null,则返回null
它的文档ConcurrentMap.computeIfAbsent尝试合并并发方面,落在以下的非直觉行为putIfAbsent:
实施要求:
默认实现等效于此映射的以下步骤,然后返回当前值,如果现在不存在则返回null:
Run Code Online (Sandbox Code Playgroud)if (map.get(key) == null) { V newValue = mappingFunction.apply(key); if (newValue != null) return map.putIfAbsent(key, newValue); }
但它仍然说
返回:
与指定键关联的当前(现有或已计算)值,如果计算值为null,则返回null
并且记录的意图应该优先于代码示例.请注意,实际default执行情况ConcurrentMap.computeIfAbsent符合记录的意图:
Run Code Online (Sandbox Code Playgroud)@Override default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) { Objects.requireNonNull(mappingFunction); V v, newValue; return ((v = get(key)) == null && (newValue = mappingFunction.apply(key)) != null && (v = putIfAbsent(key, newValue)) == null) ? newValue : v; }
因此,实现ConcurrentHashMap.computeIfAbsent确实符合两者的记录意图,ConcurrentMap.computeIfAbsent并且Map.computeIfAbsent关于返回值,并且也等同于default接口提供的实现.
为了完整性,default执行Map.computeIfAbsent是
Run Code Online (Sandbox Code Playgroud)default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) { Objects.requireNonNull(mappingFunction); V v; if ((v = get(key)) == null) { V newValue; if ((newValue = mappingFunction.apply(key)) != null) { put(key, newValue); return newValue; } } return v; }