Java中Map 接口的一些新增方法

getOrDefault方法

这个很好理解,如果get(key)为空,就返回传入的默认值,否则直接返回。

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

putIfAbsent方法

这个很好理解,如果当前key对应value为空,就进行put。否则不做事。

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

merge方法

这个方法传入的是key, value,如果 oldValue为空,那入参value就直接赋值给newValue,否则就执行lambda表达式的计算,如果计算出的结果为空,就执行key的删除。

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

compute方法

直接看代码

	default V compute(K key,
            BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
    
    
        Objects.requireNonNull(remappingFunction);
        V oldValue = get(key);
        //通过传入的函数式接口计算出新value
        V newValue = remappingFunction.apply(key, oldValue);
        //如果新value为空,否则什么也不做。
        if (newValue == null) {
    
    
            // 旧value不为空,或者map中存在当前key就删除(这个是考虑key对应的oldValue就是null)
            if (oldValue != null || containsKey(key)) {
    
    
                remove(key);
                return null;
            } else {
    
    //否则什么也不做
                return null;
            }
        } else {
    
    
            //如果新value不为空,就相当于普通的put方法
            put(key, newValue);
            return newValue;
        }
    }

所以compute方法就是给它一个键和lambda表达式(函数式接口Function应该都知道,BiFunction就是两个参数的Function接口),如果这个lambda表达式计算出的结果为null,就进行map的删除,否则就进行普通的put。

所以merge和compute方法的区别就是在入参lambda表达式和在remove(key)时的区别。

  • merge可以手动设置一个入参value,方便外部设置。lambda表达式的参数是入参val和oldVal。在remove(key)时不会检查map中是否存在key
  • compute入参没有value。lambda表达式的参数是key和oldVal。在remove(key)时会检查map中是否存在key,如果不存在就不执行删除。不过compute这个return写的真难看。。直接和merge一样最后写return不就好了。。

举个例子,比如要统计每个元素出现的次数。

public static void main(String[] args) throws IOException {
    
    
    Map<Integer, Integer> map = new HashMap<>();
    int[] nums = {
    
    1, 2, 3, 1, 42, 32, 33, 131, 131, 2, 3, 3, 3, 1, 3, 42};
    //如果你不知道getOrDefault就可能会这样做
    for (int num : nums) {
    
    
      Integer cnt = map.get(num);
      if (cnt == null) map.put(num, 1);
      else map.put(num, cnt + 1);
    }
    //如果你知道可能会这样做
    for (int num : nums) {
    
    
      map.put(num, map.getOrDefault(num, 0) + 1);
    }
    //如果你知道merge,可以这样
    for (int num : nums) {
    
    
      map.merge(num, 1, (old, val) -> old + val);
    }
    //如果你知道compute,那还可以这样做。
    //这里看着比上面还长,但是如果在计算新value的时候如果需要同时用到
    //oldValue和key那么这个方法就可以省去一些判断
    for (int num : nums) {
    
    
      map.compute(num, (key, old) -> old == null ? 1 : old + 1);
    }
  }

computeIfAbsent方法

这个方法看名字也容易理解,如果key对应的value为null才进行操作,否则什么也不做。
但是和compute方法有区别,计算新value的时候参数只有key,也就是传入的key。

	default V computeIfAbsent(K key,
            Function<? super K, ? extends V> mappingFunction) {
    
    
        Objects.requireNonNull(mappingFunction);
        V v;
        if ((v = get(key)) == null) {
    
    
            V newValue;
            //通过key计算出新value,并且新value不为null时才进行put
            if ((newValue = mappingFunction.apply(key)) != null) {
    
    
                put(key, newValue);
                return newValue;
            }
        }
        return v;
    }

computeIfPresent方法

和上面的相反,如果通过传入的key得到的value不为空才进行操作,否则什么也不做。
和compute方法一样,计算新value时参数是两个,分别为传入的key和oldValue。

	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);
            //如果新value
            if (newValue != null) {
    
    
                put(key, newValue);
                return newValue;
            } else {
    
    
                remove(key);
                return null;
            }
        } else {
    
    
            return null;
        }
    }

replace方法

key对应的value如果和oldValue相同,就替换为newValue,否则不做事。

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

猜你喜欢

转载自blog.csdn.net/qq_42007742/article/details/109038858