Java集合源码分析(十四)-Map(三)默认方法

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情

默认方法

public interface Map<K,V> {
    // Defaultable methods

    default V getOrDefault(Object key, V defaultValue) {
        V v;
        return (((v = get(key)) != null) || containsKey(key))
            ? v
            : defaultValue;
    }

    default void forEach(BiConsumer<? super K, ? super V> action) {
        Objects.requireNonNull(action);
        for (Map.Entry<K, V> entry : entrySet()) {
            K k;
            V v;
            try {
                k = entry.getKey();
                v = entry.getValue();
            } catch(IllegalStateException ise) {
                // this usually means the entry is no longer in the map.
                throw new ConcurrentModificationException(ise);
            }
            action.accept(k, v);
        }
    }

    default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
        Objects.requireNonNull(function);
        for (Map.Entry<K, V> entry : entrySet()) {
            K k;
            V v;
            try {
                k = entry.getKey();
                v = entry.getValue();
            } catch(IllegalStateException ise) {
                // this usually means the entry is no longer in the map.
                throw new ConcurrentModificationException(ise);
            }

            // ise thrown from function is not a cme.
            v = function.apply(k, v);

            try {
                entry.setValue(v);
            } catch(IllegalStateException ise) {
                // this usually means the entry is no longer in the map.
                throw new ConcurrentModificationException(ise);
            }
        }
    }

    default V putIfAbsent(K key, V value) {
        V v = get(key);
        if (v == null) {
            v = put(key, value);
        }

        return v;
    }

    default boolean remove(Object key, Object value) {
        Object curValue = get(key);
        if (!Objects.equals(curValue, value) ||
            (curValue == null && !containsKey(key))) {
            return false;
        }
        remove(key);
        return true;
    }

    default boolean replace(K key, V oldValue, V newValue) {
        Object curValue = get(key);
        if (!Objects.equals(curValue, oldValue) ||
            (curValue == null && !containsKey(key))) {
            return false;
        }
        put(key, newValue);
        return true;
    }

    default V replace(K key, V value) {
        V curValue;
        if (((curValue = get(key)) != null) || containsKey(key)) {
            curValue = put(key, value);
        }
        return curValue;
    }

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

    default V computeIfPresent(K key,
            BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
        Objects.requireNonNull(remappingFunction);
        V oldValue;
        if ((oldValue = get(key)) != null) {
            V newValue = remappingFunction.apply(key, oldValue);
            if (newValue != null) {
                put(key, newValue);
                return newValue;
            } else {
                remove(key);
                return null;
            }
        } else {
            return null;
        }
    }

    default V compute(K key,
            BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
        Objects.requireNonNull(remappingFunction);
        V oldValue = get(key);

        V newValue = remappingFunction.apply(key, oldValue);
        if (newValue == null) {
            // delete mapping
            if (oldValue != null || containsKey(key)) {
                // something to remove
                remove(key);
                return null;
            } else {
                // nothing to do. Leave things as they were.
                return null;
            }
        } else {
            // add or replace old mapping
            put(key, newValue);
            return newValue;
        }
    }

    default V merge(K key, V value,
            BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
        Objects.requireNonNull(remappingFunction);
        Objects.requireNonNull(value);
        V oldValue = get(key);
        V newValue = (oldValue == null) ? value :
                   remappingFunction.apply(oldValue, value);
        if(newValue == null) {
            remove(key);
        } else {
            put(key, newValue);
        }
        return newValue;
    }
}
复制代码
  • default V getOrDefault(Object key, V defaultValue):返回指定 key 映射的 value,如果这个 map 不包含 key 的映射,则返回默认值
    • 默认实现不保证这个方法的同步或者原子属性。任何提供原子保证的实现必须重写这个方法并且记录他的并发属性
  • default void forEach(BiConsumer<? super K, ? super V> action):对这个 map 每个 entry 执行指定的操作,直到全部 entry 已经被处理完或者操作抛出异常。除非实现类另外指定,否则操作按照 entry set 迭代顺序执行(如果指定迭代顺序)
    • 默认实现等效于
    for (Map.Entry<K, V> entry : map.entrySet())
        action.accept(entry.getKey(), entry.getValue());
    复制代码
    • 默认实现不保证这个方法的同步或者原子属性。任何提供原子保证的实现必须重写这个方法并且记录他的并发属性
  • default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function):通过对 entry 调用给定方法的结果替换每个 entry 的 value,直到处理完全部 entry 或者函数抛出异常,函数抛出的异常以被转发到调用方
    • 默认实现等效于
    for (Map.Entry<K, V> entry : map.entrySet())
        entry.setValue(function.apply(entry.getKey(), entry.getValue()));
    复制代码
    • 默认实现不保证这个方法的同步或者原子属性。任何提供原子保证的实现必须重写这个方法并且记录他的并发属性
  • default V putIfAbsent(K key, V value):如果指定 key 没已经关联 value(或映射 null),通过给定 value 关联它,并且返回 null,否则返回当前 value
    • 默认实现等效于
    V v = map.get(key);
    if (v == null)
        v = map.put(key, value);
    return v;
    复制代码
    • 默认实现不保证这个方法的同步或者原子属性。任何提供原子保证的实现必须重写这个方法并且记录他的并发属性
  • default boolean remove(Object key, Object value):只有当指定 key 当前映射指定 value,才移除指定 key 的 entry
    • 默认实现等效于
    if (map.containsKey(key) && Objects.equals(map.get(key), value)) {
        map.remove(key);
        return true;
    } else
        return false;
    复制代码
    • 默认实现不保证这个方法的同步或者原子属性。任何提供原子保证的实现必须重写这个方法并且记录他的并发属性
  • default boolean replace(K key, V oldValue, V newValue):只有当当前映射到指定 value,才替换指定 key 的 entry
    • 默认实现等效于
    if (map.containsKey(key) && Objects.equals(map.get(key), value)) {
        map.put(key, newValue);
        return true;
    } else
        return false;
    复制代码
    • 如果旧值是 null,默认实现不会因为 map 不支持 null 值抛 NullPointerException,除非新值同样是 null
    • 默认实现不保证这个方法的同步或者原子属性。任何提供原子保证的实现必须重写这个方法并且记录他的并发属性
  • default V replace(K key, V value):替换指定 key 的 entry,当且仅当 key 当前映射一些 value
    • 默认实现等效于
    if (map.containsKey(key)) {
        return map.put(key, value);
    } else
        return null;
    复制代码
    • 默认实现不保证这个方法的同步或者原子属性。任何提供原子保证的实现必须重写这个方法并且记录他的并发属性
  • default V computeIfAbsent(K key,Function<? super K, ? extends V> mappingFunction):如果指定 key 没有和 value 真正关联(或者映射 null),尝试使用给定映射函数去完成它的 value,并且输入它的映射,除非 null
    • 如果函数返回 null,则不记录映射。如果函数它自己抛出一个(未检测)异常,异常被抛出,并且不记录映射。最常见的用法是构造一个新对象作为初始化映射 value 或记录结果,如:map.computeIfAbsent(key, k -> new Value(f(k)));
    • 或者实现多值映射,Map<K,Collection>,支持每个 key 多 value: map.computeIfAbsent(key, k -> new HashSet()).add(v);
    • 默认实现等效于这个 map 执行下面步骤,然后返回当前值,如果现在不存在,返回 null
    if (map.get(key) == null) {
        V newValue = mappingFunction.apply(key);
        if (newValue != null)
        map.put(key, newValue);
    }
    复制代码
    • 默认实现不保证这个方法的同步或者原子属性。任何提供原子保证的实现必须重写这个方法并且记录他的并发属性
    • 贴别是,子接口 ConcurrentMap 的全部实现必须记录函数是否只有当 value 不存在时以原子方式应用一次
  • default V computeIfPresent(K key,BiFunction<? super K, ? super V, ? extends V> remappingFunction):如果指定 key 的 value 存在并且 non-null,尝试在给定 key 和它当前映射 value 下去完成一个新映射
    • 如果函数返回 null,映射被移除。如果函数本身抛出(未检测)异常,异常被重新抛出,并且当前映射保持不变
    • 默认实现等效于这个 map 执行下列步骤,然后返回当前 value,如果现在不存在,返回 null
    if (map.get(key) != null) {
        V oldValue = map.get(key);
        V newValue = remappingFunction.apply(key, oldValue);
        if (newValue != null)
            map.put(key, newValue);
        else
            map.remove(key);
    }
    复制代码
    • 默认实现不保证这个方法的同步或者原子属性。任何提供原子保证的实现必须重写这个方法并且记录他的并发属性
    • 贴别是,子接口 ConcurrentMap 的全部实现必须记录函数是否只有当 value 不存在时以原子方式应用一次
  • default V compute(K key,BiFunction<? super K, ? super V, ? extends V> remappingFunction):尝试计算指定 key 和它当前映射值(如果当前没有映射,为 null)的映射。例如,创建或附加 String 消息到 value 映射
    • map.compute(key, (k, v) -> (v == null) ? msg : v.concat(msg)) (方法 merge 对这种目的经常更容易使用)
    • 如果函数返回 null,映射被移除(或者初始化缺少时依然缺少)。如果函数它自己抛出(未检测)异常,异常被重新抛出,并且当前映射保持不变
    • 默认实现等效于对这个 map 执行下面步骤,然后返回当前值,如果不存在,返回 null
    V oldValue = map.get(key);
    V newValue = remappingFunction.apply(key, oldValue);
    if (oldValue != null ) {
        if (newValue != null)
            map.put(key, newValue);
        else
            map.remove(key);
    } else {
        if (newValue != null)
            map.put(key, newValue);
        else
            return null;
     }
    复制代码
    • 默认实现不保证这个方法的同步或者原子属性。任何提供原子保证的实现必须重写这个方法并且记录他的并发属性
    • 贴别是,子接口 ConcurrentMap 的全部实现必须记录函数是否只有当 value 不存在时以原子方式应用一次
  • default V merge(K key, V value,BiFunction<? super V, ? super V, ? extends V> remappingFunction):如果指定 key 没有真正与 value 关联,或者关联 null,关联它通过给定 non-null value。否则,通过给定映射方法的结果替代关联的值,或者如果结果是 null 则移除。当 key 组合多个映射 value,可以使用这方法。例如,创建或者附加 msg 到 value 映射:map.merge(key, msg, String::concat)
    • 如果函数返回 null,映射被移除。如果函数它自己抛出(未检测)异常,异常被重新抛出,并且当前映射保持不变
    • 默认实现等效于对这个 map 执行下面步骤,然后返回当前值,如果不存在,返回 null
    V oldValue = map.get(key);
    V newValue = (oldValue == null) ? value : remappingFunction.apply(oldValue, value);
    if (newValue == null)
        map.remove(key);
    else
        map.put(key, newValue);
    复制代码
    • 默认实现不保证这个方法的同步或者原子属性。任何提供原子保证的实现必须重写这个方法并且记录他的并发属性
    • 贴别是,子接口 ConcurrentMap 的全部实现必须记录函数是否只有当 value 不存在时以原子方式应用一次

猜你喜欢

转载自juejin.im/post/7106296262416138247