本文介绍了Oracle Java 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 的非直观行为引起的错误,而实施则遵循记录的意图。这已在
和已在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

请注意是

if (map.get(key) == null) {
    V newValue = mappingFunction.apply(key);
    if (newValue != null)
        map.put(key, newValue);
}


省略返回语句。但是明确地说

omitting the return statement. But clearly says

这是尝试合并并发方面,属于 putIfAbsent 的非直观行为:

if (map.get(key) == null) {
    V newValue = mappingFunction.apply(key);
    if (newValue != null)
        return map.putIfAbsent(key, newValue);
}


但它仍然说

并且记录的意图应优先于代码示例。请注意实际的的实现与记录的意图一致:

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;
}


所以的实现确实符合两者的记录意图, 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的错误实现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-18 01:30