Oracle Java ConcurrentHashMap的错误实现? [英] Wrong implementation of Oracle Java ConcurrentHashMap?
问题描述
我正在测试 关于Oracle Java 8实现的ConcurrentHashMap
:
I am testing ConcurrentHashMap
on Oracle's Java 8 implementation:
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
实施要求:
默认实现等效于此映射的以下步骤,然后返回当前值,如果现在不存在则返回null:
The default implementation is equivalent to the following steps for this map, then returning the current value or null if now absent:
if (map.get(key) == null) {
V newValue = mappingFunction.apply(key);
if (newValue != null)
return map.putIfAbsent(key, newValue);
}
它说然后返回当前值,如果现在不存在则为null 。所以不应该返回 null
?鉴于 putIfAbsent
也返回 null
。
It said then returning the current value or null if now absent. So shouldn't it be returning null
? Given that putIfAbsent
is also returning null
.
什么我在这里错过了吗?
What am I missing here?
推荐答案
的代码示例ConcurrentMap.computeIfAbsent
没有反映实际意图,很可能是由 putIfAbsent
的非直观行为引起的错误,而实施则遵循记录的意图。这已在 JDK-8174087
和已在Java 9中修复
The code example of ConcurrentMap.computeIfAbsent
is not reflecting the actual intention, most likely a mistake caused by the non-intuitive behavior of putIfAbsent
, while the implementation obeys the documented intention. This has been reported in JDK-8174087
and fixed in Java 9
请注意 Map.computeIfAbsent
是
实施要求:
默认实施相当于以下步骤map,然后返回当前值,如果现在不存在则返回null:
Implementation Requirements:
The default implementation is equivalent to the following steps for this map, then returning the current value or null if now absent:
if (map.get(key) == null) {
V newValue = mappingFunction.apply(key);
if (newValue != null)
map.put(key, newValue);
}
省略返回
语句。但是明确地说
omitting the return
statement. But clearly says
返回:
当前(现有的或已计算的)值与指定键关联,如果计算值为null,则返回null
Returns:
the current (existing or computed) value associated with the specified key, or null if the computed value is null
这是 ConcurrentMap.computeIfAbsent
尝试合并并发方面,属于 putIfAbsent
的非直观行为:
实施要求:
默认实现相当于此地图的以下步骤,然后返回当前值,如果现在不存在则为null:
Implementation Requirements:
The default implementation is equivalent to the following steps for this map, then returning the current value or null if now absent:
if (map.get(key) == null) {
V newValue = mappingFunction.apply(key);
if (newValue != null)
return map.putIfAbsent(key, newValue);
}
但它仍然说
返回:
与指定键关联的当前(现有或计算)值,或者如果计算值为null,则返回null
Returns:
the current (existing or computed) value associated with the specified key, or null if the computed value is null
并且记录的意图应优先于代码示例。请注意实际的 默认
ConcurrentMap.computeIfAbsent
的实现与记录的意图一致:
and the documented intention should have precedence over a code example. Note that the actual default
implementation of ConcurrentMap.computeIfAbsent
is in line with the documented intention:
@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
关于返回值,也等同于默认
接口提供的实现。
So the implementation of ConcurrentHashMap.computeIfAbsent
does conform to the documented intention of both, ConcurrentMap.computeIfAbsent
and Map.computeIfAbsent
regarding the returned value and is also equivalent to the default
implementation provided by the interfaces.
For completeness, the default
implementation of Map.computeIfAbsent
is
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;
}
这篇关于Oracle Java ConcurrentHashMap的错误实现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!