欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

使用Java8 Stream API对Map按键或值进行排序

程序员文章站 2022-07-04 23:53:31
一、什么是Java 8 Stream 使用Java 8 Streams,我们可以按键和按值对映射进行排序。下面是它的工作原理: 1. 将Map或List等集合类对象转换为Stream对象 2. 使用Streams的 方法对其进行排序 3. 最终将其返回为 (可以保留排序顺序) 方法以 作为参数,从而 ......

一、什么是java 8 stream

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

使用Java8 Stream API对Map按键或值进行排序

  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()返回hashmaphashmap不能保证元素的顺序。

如果希望按照键进行逆向排序,加入下图中红色部分代码即可。
使用Java8 Stream API对Map按键或值进行排序

四、按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

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

期待您的关注