Oracle Java ConcurrentHashMap的错误实现? [英] Wrong implementation of Oracle Java ConcurrentHashMap?

查看:175
本文介绍了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

Javadoc computeIfAbsent 确实说


实施要求:

默认实现等效于此映射的以下步骤,然后返回当前值,如果现在不存在则返回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.

为了完整性,默认实现/grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/Map.java#Map.computeIfAbsent%28java.lang.Object%2Cjava.util.function.Function %29rel =noreferrer> Map.computeIfAbsent

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆