为何排序HashMap<T,T>需先转为Map.Entry列表再执行排序?
疑问:为何HashMap按值排序必须先转为Map.Entry列表?
我遇到了按值排序HashMap<String, Integer>的问题,网上多数方案都是先创建Map.Entry<String, Integer>的LinkedList/ArrayList,再基于值进行排序。以下是一段展示按值排序HashMap的代码片段:
// Java program to sort hashmap by values import java.util.*; import java.lang.*; public class Main { // function to sort hashmap by values public static HashMap<String, Integer> sortByValue(HashMap<String, Integer> hm) { // Create a list from elements of HashMap List<Map.Entry<String, Integer> > list = new LinkedList<Map.Entry<String, Integer> >(hm.entrySet()); // Sort the list Collections.sort(list, new Comparator<Map.Entry<String, Integer> >() { public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) { return (o1.getValue()).compareTo(o2.getValue()); } }); // put data from sorted list to hashmap HashMap<String, Integer> temp = new LinkedHashMap<String, Integer>(); for (Map.Entry<String, Integer> aa : list) { temp.put(aa.getKey(), aa.getValue()); } return temp; } // Driver Code public static void main(String[] args) { HashMap<String, Integer> hm = new HashMap<String, Integer>(); // enter data into hashmap hm.put("Math", 98); hm.put("Data Structure", 85); hm.put("Database", 91); hm.put("Java", 95); hm.put("Operating System", 79); hm.put("Networking", 80); Map<String, Integer> hm1 = sortByValue(hm); // print the sorted hashmap for (Map.Entry<String, Integer> en : hm1.entrySet()) { System.out.println("Key = " + en.getKey() + ", Value = " + en.getValue()); } } }
我的疑问是:为何必须将HashMap转为Map.Entry的列表后再进行排序?我认为应该可以像对POJO类按指定参数排序那样直接对HashMap排序,无需转为其他集合再操作。
解答
1. HashMap本身不支持排序
HashMap底层基于哈希表实现,核心目标是快速查找、插入和删除,完全不维护元素的存储顺序——元素的位置由键的哈希值决定,是无序的。它既没有实现Comparable接口,也没有内置排序机制,根本没法直接对HashMap本身执行排序操作。
2. 排序需要操作完整的键值对
按值排序的核心是对比每个键值对的value,但HashMap的entrySet()返回的是无序的Set<Map.Entry>集合,而Java标准库的Collections.sort()只支持对List进行排序。所以必须把键值对转成List,才能利用现有API对这些元素按值进行比较排序。
3. 用LinkedHashMap保留排序结果
排序后的List需要存入一个能维护顺序的Map中,普通HashMap会再次打乱顺序。LinkedHashMap是HashMap的子类,它可以保留元素的插入顺序,因此把排序后的键值对依次放入LinkedHashMap,就能得到按值排序的有序Map。
补充:Java 8+简化写法
Java 8之后可以用Stream API简化代码,核心逻辑还是转集合排序,但代码更简洁:
public static Map<String, Integer> sortByValue(HashMap<String, Integer> hm) { return hm.entrySet() .stream() .sorted(Map.Entry.comparingByValue()) .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (oldVal, newVal) -> oldVal, LinkedHashMap::new )); }
内容的提问来源于stack exchange,提问作者Simran Srivastava
相关产品推荐
相关产品推荐

