一, 什么是 Java 8 Stream
使用 Java 8 Streams, 我们可以按键和按值对映射进行排序. 下面是它的工作原理:
将 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 不能保证元素的顺序.
如果希望按照键进行逆向排序, 加入下图中红色部分代码即可.
四, 按 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
如上所示, 键 (国家 / 地区名称) 以自然字母顺序排序.
期待您的关注
博主最近新写了一本书:《手摸手教您学习 SpringBoot 系列 - 16 章 97 节》 http://springboot.zimug.com/
来源: https://www.cnblogs.com/zimug/p/11781375.html