Map接口总结(如何使用默认方法)

default方法

排序在前的方法较为常用。

默认方法是为了在标准库中添加默认支持函数式方法,同时也不必修改现有的类,这样做虽然有一定的好处,但是实际上在子类中使用default方法还是极有可能出错的,因为一个default方法无法满足所有的子类,也不可能满足。如果随意使用default方法,可能破坏了原有子类的一致性,产生意想不到的问题。

在标准库中,除了并发相关类,比如ConcurrentHashMap等,一般没有问题。

但是在其他类库的实现类中使用一定要慎之又慎,比如使用一个老版本的Map子类。

引入default方法破坏了前向兼容性,容易产生运行时异常。

V getOrDefault(Object key, V defaultValue) 常用,获取值或者默认值,可类比Optional.orElse。

以下是先做判断,后计算的(if true)

V putIfAbsent(K key, V value)

V replace(K key, V value) 感觉叫putIfPresent更好

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

boolean remove(Object key, Object value) 如果匹配的话,remove

以下四个方法为一组,都是对entry(k, v)的更新,只是条件不一样。

V computeIfAbsent(K key,
                Function mappingFunction)
// 如果没有entry则更新
// 返回值为value,可以用于后续操作
// 常用于MultiMap,如下面一句话表示把用户添加到用户组里
map.computeIfAbsent(userGroup, k -> new HashMap()).add(user);
 V computeIfPresent(K key,
        BiFunction remappingFunction)
// 如果有entry则更新
V compute(K key,
        BiFunction remappingFunction)
// 不常用,因为如果不包含entry则可能抛出空指针异常
// 可以理解为同时支持上面两个方法,但是我们一般都需要对是否包含entry进行判断,所以不常用。
// compute方法也可以实现merge这样的规约操作,既然如此,在需要规约操作时,我们为什么不用merge呢。
// v 可能为空指针,程序员极有可能忘记检查,编译器也不能帮助检查。
// 总之,这个compute方法不常用。

// compute进行null判断
map.compute(key, (k, v) -> (v == null) ? msg : v.concat(msg))
// merge中更简单
map.merge(key, msg, String::concat)
V merge(K key, V value,
        BiFunction remappingFunction)
// 没有则使用默认值,有则进行类似reduce的操作
// 规约结果为null时,则删除
// 好用
// 常用来计数
map.merge(key, 1, Integer::sum);
void replaceAll(BiFunction function)
// 使用泛型达到了更广的匹配
// 通配符使用原则,使用的对象 (consumer) 使用 super,生成的对象 (provider) 使用 extends。

forEach(BiConsumer<? super K, ? super V> action)

!!!经常滥用的方法,不建议使用,action只建议使用简单的逻辑。每回看到别人使用forEach方法都感觉很恶心,这个方法看上去好用,可以传入(k,v)→ … lambda表达式,但是函数式方法应该尽量不产生副作用,使用函数式方法的目的应该便于理解。然而在项目中经常看到大段的lambda表达式传入,在不便于调试的同时,还不能产生副作用。由于副作用的问题,每回想修改forEach的逻辑时,都必须改为for (Map.Entry

包括Collections下的List,Set等都有滥用forEach方法。

以下是我在网上找的一个例子,不知道你看到forEach后啥感觉,我反正是要吐了,况且这还是一段逻辑相对简单的代码。

public static void main(String[] args)
    {

        // create a HashMap and add some values
        HashMap
            map1 = new HashMap<>();
        map1.put(1, "Ram");
        map1.put(2, "Rohan");
        map1.put(3, "Shivam");

        HashMap
            map2 = new HashMap<>();
        map2.put(1, "Tushar");
        map2.put(10, "Satya");
        map2.put(12, "Sundar");

        // print map details
        System.out.println("HashMap1: "
                           + map1.toString());

        System.out.println("HashMap2: "
                           + map2.toString());

        // provide value for new key which is absent
        // using computeIfAbsent method
        map2.forEach(
            (key, value)
                -> map1.merge(
                    key,
                    value,
                    (v1, v2)
                        -> v1.equalsIgnoreCase(v2)
                               ? v1
                               : v1 + ", " + v2));

        // print new mapping
        System.out.println("New HashMap: " + map1);
    }

总之,函数式方法使用的函数应该足够简单,便于理解。

如果使用默认方法可以简化了理解,代码更简洁,而且没有副作用,确保代码兼容性,可以使用默认方法,其他情况下还是老老实实用命令式编程吧。

Original: https://www.cnblogs.com/dahua-dijkstra/p/16124487.html
Author: 大华dijkstra
Title: Map接口总结(如何使用默认方法)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/713863/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 车联网人物专访|大家好,我是橡树,“搞”车是件很酷的事

    近年来,随着我国智能网联汽车大面积覆盖市场,车联网安全领域踊跃出一批”江湖大佬”。也许你未曾见过大佬的真容,但ta的名字一定时常在耳边响起。今天我们有幸邀请…

    技术杂谈 2023年5月31日
    087
  • 线索二叉树相关问题

    线索二叉树相关问题 1.在先序线索二叉树中求解指针P的后继结点 binode presuc(Binode *p){ if(p->rtag==1) return p->r…

    技术杂谈 2023年7月23日
    060
  • DevEco Studio3.0下载失败,提示An unknown error occurred

    【问题描述】下载OpenHarmony Sdk时报错 eTS下载失败,下载的都失败下载HarmonyOS Legacy SDK时报错 JS失败Error: Install JS 3…

    技术杂谈 2023年5月31日
    068
  • 部署-jenkins发布项目到linux环境

    使用openSSH的方式 如果jenkins跟服务器不在同一台服务器上,这时候我们可以借助ssh的方式将打包好的jar包发送到远程服务器,然后以后台的方式运行程序。 安装publi…

    技术杂谈 2023年7月23日
    070
  • 说说用户线程和守护线程

    什么是用户线程和守护线程? 守护线程是一种特殊的线程,在后台默默地完成一些系统性的服务,比如 垃圾回收线程、 JIT线程都是 守护线程。与之对应的是 用户线程,用户线程可以理解为是…

    技术杂谈 2023年6月21日
    0102
  • python异常处理

    关于异常 在程序运行中,总会遇到各种各样的错误,如打开一个不存在的文件,程序期待用户输入数字,但用户输入了字符串,网络传输终止等,如果不对这些可能引发异常的情况进行处理,就会导致抛…

    技术杂谈 2023年7月11日
    067
  • python的基本运用

    python基础 Python语言是一种解释型、面向对象、动态数据类型的高级程序设计语言 开发者:Guido van Rossum(人称龟叔) 基本概念 1.变量 变量名必须是大小…

    技术杂谈 2023年7月11日
    084
  • 设置描述性弹性域某个字段为只读

    设置一个值集,假设值集名为CUX_ONLYREAD 验证类型设置为特定 点击编辑信息 上部分事件选择编辑,函数为 FND SQL “BEGIN NULL;END;&#8…

    技术杂谈 2023年6月1日
    071
  • Linux命令

    linus/终端的常用快捷键 【ll】 显示当前目录的所有文件【详】【ls】 显示当前目录的所有文件【略】【ls /路径】显示该路径下的所有文件 【cd ..】 进入上级目录【./…

    技术杂谈 2023年7月24日
    093
  • Windows下 webpack4.0 的安装

    这里我们通过npm来进行安装 1. 安装 webpack // 全局安装webpack npm install webpack -g 2. 通过 webpack -v 命令查看当前…

    技术杂谈 2023年5月31日
    0108
  • AIX下安装bash

    在AIX系统下,默认是没有安装bash环境的,对于经常操作的维护人员来说,非常不方便,所以下面我们来动手安装bash。 1、确认系统是否已安装bash 方法1:之间敲bash命令,…

    技术杂谈 2023年7月10日
    072
  • 【JavaWeb】JDK动态代理 – 代理模式;静态代理;动态代理;JDK动态代理的实现及实现原理分析

    需要掌握的程度: 什么是JDK动态代理 ? 使用jdk的反射机制,创建对象的能力(创建的是代理类的对象),而不用创建类文件,不用写java文件。 动态:在程序执行时,调用jdk提供…

    技术杂谈 2023年7月10日
    065
  • 力扣刷题之路-数组的遍历

    参考刷题顺序:力扣刷题顺序 本文章做自我总结,总结做题时自己的想法以及官方解题思路。 涉及题目 485 最大连续 1 的个数 495 提莫攻击 414 第三大的数 628 三个数的…

    技术杂谈 2023年7月11日
    072
  • 差分数组入门

    差分数组 什么是差分数组? 差分数组:差分数组就是原始数组相邻元素之间的差。 其实差分数组是一个 辅助数组,从侧面来表示给定某一数组的变化,一般用来对数组进行区间修改的操作。 比如…

    技术杂谈 2023年6月21日
    0108
  • ClickHouse-查询优化

    单表查询【使用的频率高】 Prewhere 和 where 语句的作用相同,用来过滤数据。不同之处在于 prewhere 只支持*MergeTree 族系列引擎的表,首先会读取指定…

    技术杂谈 2023年7月10日
    061
  • 安装cuda和cudnn

    原来机器上有安装一个cuda 10.0,想要再安装一个cuda 10.1 安装CUDA 1.首先下载.run文件 https://developer.nvidia.com/cuda…

    技术杂谈 2023年6月1日
    069
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球