如何利用Java8 Stream API对Map按键或值排序

 更新时间:2019年11月02日 15:16:55   作者:字母哥博客  
这篇文章主要给大家介绍了关于如何利用Java8 Stream API对Map按键或值排序的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用Java8具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

一、什么是Java 8 Stream

使用Java 8 Streams,我们可以按键和按值对映射进行排序。下面是它的工作原理:

Java Stream函数式编程?用过都说好,案例图文详解送给你

  1. 将Map或List等集合类对象转换为Stream对象
  2. 使用Streams的sorted()方法对其进行排序
  3. 最终将其返回为LinkedHashMap(可以保留排序顺序)

sorted()方法以Comparator作为参数,从而可以按任何类型的值对Map进行排序。如果对Comparator不熟悉,可以看本号前几天的文章,有一篇文章专门介绍了使用Comparator对List进行排序。

二、学习一下HashMap的merge()函数

在学习Map排序之前,有必要讲一下HashMap的merge()函数,该函数应用场景就是当Key重复的时候,如何处理Map的元素值。这个函数有三个参数:

  • 参数一:向map里面put的键
  • 参数二:向map里面put的值
  • 参数三:如果键发生重复,如何处理值。可以是一个函数,也可以写成lambda表达式。
    String k = "key";
    HashMap<String, Integer> map = new HashMap<String, Integer>() {{
      put(k, 1);
    }};
    map.merge(k, 2, (oldVal, newVal) -> oldVal + newVal);

看上面一段代码,我们首先创建了一个HashMap,并往里面放入了一个键值为k:1的元素。当我们调用merge函数,往map里面放入k:2键值对的时候,k键发生重复,就执行后面的lambda表达式。表达式的含义是:返回旧值oldVal加上新值newVal(1+2),现在map里面只有一项元素那就是k:3。

其实lambda表达式很简单:表示匿名函数,箭头左侧是参数,箭头右侧是函数体。函数的参数类型和返回值,由代码上下文来确定。

三、按Map的键排序

下面一个例子使用Java 8 Stream按Map的键进行排序:

// 创建一个Map,并填入数据
Map<String, Integer> codes = new HashMap<>();
codes.put("United States", 1);
codes.put("Germany", 49);
codes.put("France", 33);
codes.put("China", 86);
codes.put("Pakistan", 92);

// 按照Map的键进行排序
Map<String, Integer> sortedMap = codes.entrySet().stream()  
    .sorted(Map.Entry.comparingByKey())
    .collect(
        Collectors.toMap(
          Map.Entry::getKey, 
          Map.Entry::getValue,
          (oldVal, newVal) -> oldVal,
          LinkedHashMap::new
        )
    );

// 将排序后的Map打印
sortedMap.entrySet().forEach(System.out::println);

看上文中第二段代码:

  • 首先使用entrySet().stream() 将Map类型转换为Stream流类型。
  • 然后使用sorted方法排序,排序的依据是Map.Entry.comparingByKey(),也就是按照Map的键排序
  • 最后用collect方法将Stream流转成LinkedHashMap。 其他参数都好说,重点看第三个参数,就是一个merge规则的lambda表达式,与merge方法的第三个参数的用法一致。由于本例中没有重复的key,所以新值旧值随便返回一个即可。

上面的程序将在控制台上打印以下内容,键(国家/地区名称)以自然字母顺序排序:

China=86
France=33
Germany=49
Pakistan=92
United States=1

请注意使用LinkedHashMap来存储排序的结果以保持顺序。默认情况下,Collectors.toMap()返回HashMap。HashMap不能保证元素的顺序。

如果希望按照键进行逆向排序,加入下图中红色部分代码即可。


四、按Map的值排序

当然,您也可以使用Stream API按其值对Map进行排序:

Map<String, Integer> sortedMap2 = codes.entrySet().stream()
    .sorted(Map.Entry.comparingByValue())
    .collect(Collectors.toMap(
        Map.Entry::getKey,
        Map.Entry::getValue,
        (oldVal, newVal) -> oldVal,
        LinkedHashMap::new));

sortedMap2.entrySet().forEach(System.out::println);

这是显示Map按值排序的输出:

United States=1
France=33
Germany=49
China=86
Pakistan=92

五、使用TreeMap按键排序

大家可能都知道TreeMap内的元素是有顺序的,所以利用TreeMap排序也是可取的一种方法。您需要做的就是创建一个TreeMap对象,并将数据从HashMapput到TreeMap中,非常简单:

// 将 `HashMap` 转为 `TreeMap`
Map<String, Integer> sorted = new TreeMap<>(codes);

这是输出:

China=86
France=33
Germany=49
Pakistan=92
United States=1

如上所示,键(国家/地区名称)以自然字母顺序排序。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。

原文链接:https://www.cnblogs.com/zimug/p/11781375.html

相关文章

  • SpringBoot log打印及输出方式

    SpringBoot log打印及输出方式

    这篇文章主要介绍了SpringBoot log打印及输出方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • SpringBoot与docker的结合的示例

    SpringBoot与docker的结合的示例

    本篇文章主要介绍了SpringBoot与docker的结合的示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-03-03
  • MyBatis将查询出的两列数据装配成键值对的操作方法

    MyBatis将查询出的两列数据装配成键值对的操作方法

    这篇文章主要介绍了MyBatis将查询出的两列数据装配成键值对的操作代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-08-08
  • Java完全二叉树的创建与四种遍历方法分析

    Java完全二叉树的创建与四种遍历方法分析

    这篇文章主要介绍了Java完全二叉树的创建与四种遍历方法,结合实例形式分析了完全二叉树的概念、定义及遍历操作相关实现技巧,并对比分析了满二叉树与完全二叉树的区别,需要的朋友可以参考下
    2017-11-11
  • SpringBoot整合Java DL4J实现情感分析系统

    SpringBoot整合Java DL4J实现情感分析系统

    在当今数字化时代,企业越来越重视用户的反馈,以不断改进产品和服务,自然语言处理技术为分析用户评价提供了强大的工具,本文将介绍如何使用 Spring Boot 整合 Java Deeplearning4j 构建一个情感分析系统,需要的朋友可以参考下
    2024-10-10
  • Mybatis枚举类型转换源码分析

    Mybatis枚举类型转换源码分析

    在Mybatis的TypeHandlerRegistry中,添加了常用的类转换器,其中默认的枚举类型转换器是EnumTypeHandler,这篇文章主要介绍了Mybatis枚举类型转换源码分析,需要的朋友可以参考下
    2024-05-05
  • SpringBoot中Redis的缓存更新策略详解

    SpringBoot中Redis的缓存更新策略详解

    这篇文章主要介绍了SpringBoot中Redis的缓存更新策略,缓存一般是为了应对高并发场景、缓解数据库读写压力,而将数据存储在读写更快的某种存储介质中(如内存),以加快读取数据的速度,需要的朋友可以参考下
    2023-08-08
  • SpringBoot中整合MyBatis-Plus的方法示例

    SpringBoot中整合MyBatis-Plus的方法示例

    这篇文章主要介绍了SpringBoot中整合MyBatis-Plus的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • Java实现登录与注册页面

    Java实现登录与注册页面

    这篇文章主要为大家详细介绍了Java实现登录与注册页面,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • QQ好友列表树形列表java代码实现代码

    QQ好友列表树形列表java代码实现代码

    这篇文章主要为大家详细介绍了QQ好友列表树形列表简单实现方式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-08-08

最新评论