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

  • Map的基本使用

  • 默认方法的问题,有什么坑

  • 常用的默认方法应用场景

  • 基本操作

    get

    put(区别:Collection接口中添加为set)

    putAll

    remove

    containsKey

    containsValue

    size

    clear

  • 遍历操作

    keySet()

    values()

    entrySet()

  • 实现规约

    以下两个方法提示实现类需要重写用来比较相等的方法。

    equals

    hashcode

    以下两个方法是标准库的约定,但是Java中接口不支持定义构造器约束,只能保证标准库中都实现了这两个方法。

    构造器(空参数)

    构造器(Map other)

  • 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<? super K, ? extends V> mappingFunction)
    // 如果没有entry则更新
    // 返回值为value,可以用于后续操作
    // 常用于MultiMap,如下面一句话表示把用户添加到用户组里
    map.computeIfAbsent(userGroup, k -> new HashMap<User>()).add(user);
     V computeIfPresent(K key,
    BiFunction<? super K, ? super V, ? extends V> remappingFunction)
    // 如果有entry则更新
    V compute(K key,
    BiFunction<? super K, ? super V, ? extends V> 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<? super V, ? super V, ? extends V> remappingFunction)
    // 没有则使用默认值,有则进行类似reduce的操作
    // 规约结果为null时,则删除
    // 好用
    // 常用来计数
    map.merge(key, 1, Integer::sum);
    void replaceAll(BiFunction<? super K, ? super V, ? extends V> function)
    // 使用泛型达到了更广的匹配
    // 通配符使用原则,使用的对象 (consumer) 使用 super,生成的对象 (provider) 使用 extends。

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

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

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

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

    public static void main(String[] args)
    { // create a HashMap and add some values
    HashMap<Integer, String>
    map1 = new HashMap<>();
    map1.put(1, "Ram");
    map1.put(2, "Rohan");
    map1.put(3, "Shivam"); HashMap<Integer, String>
    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);
    }

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

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

Map接口总结(如何使用默认方法)的更多相关文章

  1. JDK8新特性:接口的静态方法和默认方法

    在jdk8之前,interface之中可以定义变量和方法,变量必须是public.static.final的,方法必须是public.abstract的.由于这些修饰符都是默认的,所以在JDK8之前, ...

  2. Java 8——接口中个的默认方法和静态方法

    在Java SE 8之前,interface只是事物的抽象,用来定义统一的抽象事物和描述事物的抽象行为和属性. 但是在Java SE 8中,增加了可以在interface中增加默认实现的行为和事物的静 ...

  3. java8-新特性--(接口的默认方法与静态方法)

    Java 8用默认方法与静态方法这两个新概念来扩展接口的声明. public interface Inte{ void method(); default void defaultMethod(){ ...

  4. Java8新特性第2章(接口默认方法)

    在Java中一个接口一旦发布就已经被定型,除非我们能够一次性的更新所有该接口的实现,否者在接口的添加新方法将会破坏现有接口的实现.默认方法就是为了解决这一问题的,这样接口在发布之后依然能够继续演化. ...

  5. jdk8系列一、jdk8 Lamda表达式语法、接口的默认方法和静态方法、supplier用法

    一.简介 毫无疑问,Java 8是Java自Java 5(发布于2004年)之后的最重要的版本.这个版本包含语言.编译器.库.工具和JVM等方面的十多个新特性. 在本文中我们将学习这些新特性,并用实际 ...

  6. Java8接口中的默认方法

    Java8新增特性,可以为接口中添加默认方法,实现这个接口的所有类都会继承这个方法,这样看起来,接口和类的界限就有点不明显了,同时也会带来多继承,菱形问题.这样设计的初衷是什么? 重所周知,java8 ...

  7. 一文带你认识Java8中接口的默认方法

    Java8是Oracle于2014年3月发布的一个重要版本,其API在现存的接口上引入了非常多的新方法. 例如,Java8的List接口新增了sort方法.在Java8之前,则每个实现了List接口的 ...

  8. 乐字节-Java8核心特性实战-接口默认方法

    JAVA8已经发布很久,是自java5(2004年发布)之后Oracle发布的最重要的一个版本.其中包括语言.编译器.库.工具和JVM等诸多方面的新特性,对于国内外互联网公司来说,Java8是以后技术 ...

  9. java8新特性- 默认方法 在接口中有具体的实现

    案例分析 在java8中在对list循环的时候,我们可以使用forEach这个方法对list进行遍历,具体代码如下demo所示 public static void main(String[] arg ...

  10. 紧随时代的步伐--Java8特性之接口默认方法

    1.关于Java8 自从1996年Sun公司发布Java以来,Java到目前为止已经走过21个年头,每一次的升级,都是Java语言的革新,对时代发展的适应.2014年Oracle发布Java8,而据可 ...

随机推荐

  1. 跟我读CVPR 2022论文:基于场景文字知识挖掘的细粒度图像识别算法

    摘要:本文通过场景文字从人类知识库(Wikipedia)中挖掘其背后丰富的上下文语义信息,并结合视觉信息来共同推理图像内容. 本文分享自华为云社区<[CVPR 2022] 基于场景文字知识挖掘的 ...

  2. python学习-Day9

    目录 记忆不清点回顾 今日概要 今日内容 大作业讲解 字符编码实际应用 编码与解码 如何解决乱码的问题 文件操作简介 什么是文件 代码操作文件 代码操作文件的流程 基本语法结构 使用关键字打开文件 w ...

  3. 技术管理进阶——一线Leader与大Leader的差异是什么?

    原创不易,求分享.求一键三连 ​ 前几年,因为下属的一些骚操作,Leader对我产生了误会,这导致了一些"不信任",这种不信任在短时间会让人丧失安全感,很多人会因此患得患失. 这种 ...

  4. HttpServletResponse & HttpServletRequest

    web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的一个HttpServletResponse: 如果要获取客户端请求过来的 ...

  5. c++:-2

    上节介绍C++的函数介绍:c++:-1,本节学习类与对象 类与对象 定义 类定义 class 类名称 { public: 公有成员(外部接口) private: 私有成员 protected: 保护型 ...

  6. Python版本共存、语法、变量和数据类型

    python多版本共存 主要是把两个版本的python解释器的所在路径都加入环境变量当中,之后重新命名python解释器文件名称就好 先拷贝一个启动程序,在进行改名就好 python.exe pyth ...

  7. 伪元素选择器,选择器优先级,CSS修改文字属性,CSS修改字体属性,CSS修改其他属性

    伪元素选择器 未使用元素选择器的效果 第一行:伪元素选择器:选择部分内容 第二行:伪元素选择器:选择部分内容 伪元素选择器:选择部分内容 伪元素选择器:选择部分内容 ::selection:选择指定元 ...

  8. Web Api源码(路由注册)

    这篇文章只是我学习Web API框架的输出,学习方法还是输出倒逼输入比较行得通,所以不管写的好不好,坚持下去,肯定有收获.篇幅比较长,仔细思考阅读下来大约需要几分钟. 做.NET开发有好几年时间了,从 ...

  9. 135_Power Query M语言快捷输入之输入法设置自定义短语

    博客:www.jiaopengzi.com 焦棚子的文章目录 请点击下载附件 一.背景 因为工作原因,把电脑重装了下,当敲M的时候总感觉那里不对.原来是我的M自定义短语没有同步.由于我的自定义短语还是 ...

  10. Windows环境下启动Redis报错:Could not create server TCP listening socket 127.0.0.1:6379: bind: 操作成功完成。(已解决)

    问题描述: 今天在windows环境下启动Redis时启动失败报错: 解决方案: ①运行命令:redis-cli.exe ②退出Redis ③运行命令:redis-server.exe redis.w ...