当前位置 主页 > 网站技术 > 代码类 >

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

    栏目:代码类 时间:2019-11-02 18:05

    一、什么是Java 8 Stream

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

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

    将Map或List等集合类对象转换为Stream对象 使用Streams的sorted()方法对其进行排序 最终将其返回为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不能保证元素的顺序。

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