前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Map接口在1.8版本新增的几个方法

Map接口在1.8版本新增的几个方法

作者头像
呼延十
发布2019-06-26 17:22:28
5360
发布2019-06-26 17:22:28
举报
文章被收录于专栏:呼延呼延

前言

Map接口在1.8版本新增以下几个有趣的方法,今天参考源码来学习一下.

  • getOrDefault
  • replaceAll
  • putIfAbsent
  • remove
  • replace
  • computeIfAbsent
  • computeIfPresent
  • compute
  • merge

V getOrDefault(Object key, V defaultValue)

这可以说是最常用的方法了吧,获取指定key的value,当key不存在的时候返回一个默认值,也就是第二个参数.

代码语言:javascript
复制
    default V getOrDefault(Object key, V defaultValue) {
        V v;
        return (((v = get(key)) != null) || containsKey(key))
            ? v
            : defaultValue;
    }

void replaceAll(BiFunction<? super K, ? super V, ? extends V> function)

将所有value替换成给定lambda的计算结果,lambda的作用为根据key和value算出新的value.

源代码如下:

代码语言:javascript
复制
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);
            }
        }
    }

示例代码如下:

代码语言:javascript
复制
    @Test
    public void test1() {
        Map<Integer, Integer> test = new HashMap<>();
        test.put(1, 1);
        test.put(2, 2);
        System.out.println(test.toString());

        test.replaceAll((k, v) -> k + v);
        System.out.println(test.toString());
    }

这段代码中传递了一个lambda,作用是将key和value相加作为新的value.

输出结果如下:

代码语言:javascript
复制
{1=1, 2=2}
{1=2, 2=4}

V putIfAbsent(K key, V value)

当key不存在的时候,写入新值.始终返回执行操作后的新值.

源代码如下:

代码语言:javascript
复制
default V putIfAbsent(K key, V value) {
        V v = get(key);
        if (v == null) {
            v = put(key, value);
        }

        return v;
    }

测试代码及输出如下:

代码语言:javascript
复制
    @Test
    public void test2() {
        Map<Integer, Integer> test = new HashMap<>();
        test.put(1, 1);
        test.put(2, 2);
        System.out.println(test.toString());

        test.putIfAbsent(1, 3);
        test.putIfAbsent(3, 3);
        System.out.println(test.toString());
    }
------------------------
{1=1, 2=2}
{1=1, 2=2, 3=3}

boolean remove(Object key, Object value)

如果给定的key在map中的value与给定值相等,则移除并且返回true,否则返回false.

代码语言:javascript
复制
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;
    }

replace

这个有两个重载方法.

default boolean replace(K key, V oldValue, V newValue)

当key在map中的value与给定的oldValue相等,则用newValue替换掉并且返回true,否则返回false.

代码语言:javascript
复制
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;
    }

V replace(K key, V value)

当key存在,就替换掉并且返回新值,否则返回null.

代码语言:javascript
复制
default V replace(K key, V value) {
        V curValue;
        if (((curValue = get(key)) != null) || containsKey(key)) {
            curValue = put(key, value);
        }
        return curValue;
    }

V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)

如果key不存在,则使用lambda计算并写入新值.永远返回执行操作后的新值.(可以存在,不做任何操作);放回计算的新值.

这个方法可以为一些耗时或者耗资源的操作构建本地缓存,当元素存在时直接返回,当不存在的时候进行耗时进行并存储,下一次可以直接返回.

代码语言:javascript
复制
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;
    }

测试代码及输出如下:

代码语言:javascript
复制
    @Test
    public void test3() {
        Map<Integer, Integer> test = new HashMap<>();
        test.put(1, 1);
        test.put(2, 2);
        System.out.println(test.toString());

        // 1 存在,不做任何操作
        test.computeIfAbsent(1, key -> key + 2);
        // 3 不存在,将3 +2 = 5.
        test.computeIfAbsent(3, key -> key + 2);
        System.out.println(test.toString());
    }

------------------------
{1=1, 2=2}
{1=1, 2=2, 3=5}

V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)

当key存在时,计算新值,如果新值不为空,则将新值写入,如果新值为空,则移除掉此key.返回新值或者null.

代码语言:javascript
复制
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;
        }
    }

测试代码及输出如下:

代码语言:javascript
复制
@Test
    public void test4() {
        Map<Integer, Integer> test = new HashMap<>();
        test.put(1, 1);
        test.put(2, 2);
        System.out.println(test.toString());

        // 1 存在,计算
        test.computeIfPresent(1, (key, oldValue) -> key + oldValue + 2);
        // 3 不存在,不作操作
        test.computeIfPresent(3, (key, oldValue) -> key + oldValue +  2);
        System.out.println(test.toString());
    }
-------------------------------
{1=1, 2=2}
{1=4, 2=2}

这个方法基本上是上一个方法的存在版本,但是要注意传入的lambda,参数是两个,computeIfAbsent的lambda传入key,计算值. 而computeIfPresent传入key和旧的value,并且由他们两个计算得到新的值.

V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)

直接计算新值,新值为空,则删除key并且返回null,新值不为空则写入并且返回新值.

代码语言:javascript
复制
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;
        }
    }

测试代码及输出如下:

代码语言:javascript
复制
 @Test
    public void test5() {
        Map<Integer, Integer> test = new HashMap<>();
        test.put(1, 1);
        test.put(2, 2);
        System.out.println(test.toString());

        test.compute(1, (key, oldValue) -> key + 2);
        test.compute(3, (key, oldValue) -> key + 2);
        test.compute(2, (key, oldValue) -> null);
        System.out.println(test.toString());
    }
----------------
{1=1, 2=2}
{1=3, 3=5}

测试代码中对2进行compute->null,结果是2被删除.

V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction)

使用旧值和给定的value来计算新值,如果新值为空,则删除key,不为空则写入并且返回.

注意:如果旧值为空,也就是原有的key不存在,新值等于给定值,不会再进行计算.因此下方的测试代码3=10而不是12.

代码语言:javascript
复制
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;
    }

测试代码及输出如下:

代码语言:javascript
复制
    @Test
    public void test6() {
        Map<Integer, Integer> test = new HashMap<>();
        test.put(1, 1);
        test.put(2, 2);
        System.out.println(test.toString());

        test.merge(1, 10, (v, oldV) -> v + oldV + 2);
        test.merge(3, 10, (v, oldV) -> v + oldV + 2);
        test.merge(2, 10, (v, oldV) -> null);
        System.out.println(test.toString());
    }
--------------------------
{1=1, 2=2}
{1=13, 3=10}

总结

其实看过源码就可以发现,除了Function,BiFunction等函数式接口(也就是用于lambda)的接口是新声明的,其他调用的API都是原先已有的put,get,contain等常用API,因此这些新的方法并不能算是很难用的新功能,只能算是一些免去开发人员重复工作的语法糖,我们当然要多多享受语法糖带来的便利,但是不能忘却原理,要多多熟悉再使用.

完。

ChangeLog

2019-05-13 完成

以上皆为个人所思所得,如有错误欢迎评论区指正。

欢迎转载,烦请署名并保留原文链接。

联系邮箱:huyanshi2580@gmail.com

更多学习笔记见个人博客——>呼延十

var gitment = new Gitment({ id: 'Map接口在1.8版本新增的几个方法', // 可选。默认为 location.href owner: 'hublanker', repo: 'blog', oauth: { client_id: '2297651c181f632a31db', client_secret: 'a62f60d8da404586acc965a2ba6a6da9f053703b', }, }) gitment.render('container')



本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • V getOrDefault(Object key, V defaultValue)
  • void replaceAll(BiFunction<? super K, ? super V, ? extends V> function)
  • V putIfAbsent(K key, V value)
  • boolean remove(Object key, Object value)
  • replace
    • default boolean replace(K key, V oldValue, V newValue)
      • V replace(K key, V value)
        • ChangeLog
    • V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)
    • V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)
    • V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)
    • V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction)
    • 总结
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档