Java Map排序如何按照值按照键排序
作者:Chasing Aurora
该文章主要介绍Java中三种Map(HashMap、LinkedHashMap、TreeMap)的默认排序行为及实现按键排序和按值排序的方法,每种方法结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
结论:只有 TreeMap 天生支持按键排序,HashMap/LinkedHashMap 需手动处理,按值排序所有 Map 都要额外实现

一、先理清 3 种 Map 的默认排序行为
| Map 类型 | 底层结构 | 默认排序规则 | 核心特点 |
|---|---|---|---|
| HashMap | 哈希表 | 无固定顺序(随机) | 查找快、无序、线程不安全 |
| TreeMap | 红黑树 | 按「键」自然排序(默认升序) | 有序(键)、查找效率中等、可自定义排序 |
| LinkedHashMap | 哈希表 + 链表 | 按「插入顺序」排序 | 有序(插入顺序)、查找快、保留插入顺序 |
简单说:
- 想默认按键有序 → 直接用 TreeMap;
- 想保留插入顺序 → 用 LinkedHashMap;
- 只想要查询快、不关心顺序 → 用 HashMap;
- 按值排序 → 任何 Map 都要手动处理(因为 Map 本质是「键值对映射」,值不具备天然排序索引)。
二、按「键」排序的实现方式
按键排序的核心是:键必须是可比较的(实现 Comparable 接口,如 String、Integer、Long 等),如果是自定义对象作为键,需手动指定比较规则。
1. 方式 1:用 TreeMap (默认按键升序,无需额外代码)
TreeMap 天生支持按键排序,默认是「自然升序」(比如数字从小到大、字符串按字典序)。
import java.util.TreeMap;
public class MapSortByKey {
public static void main(String[] args) {
// 1. TreeMap 默认按键自然升序排序(键是 Integer 类型,可比较)
TreeMap<Integer, String> treeMap = new TreeMap<>();
treeMap.put(3, "苹果");
treeMap.put(1, "香蕉");
treeMap.put(2, "橘子");
System.out.println("TreeMap 默认按键升序:" + treeMap);
// 输出:{1=香蕉, 2=橘子, 3=苹果}(按键 1→2→3 排序)
}
}2. 方式 2:TreeMap 自定义键排序(比如降序、自定义对象键)
如果想按键降序,或键是自定义对象(比如 User),需要传入 Comparator 接口指定排序规则。
示例 2.1:TreeMap 按键降序
import java.util.Comparator;
import java.util.TreeMap;
public class MapSortByKeyDesc {
public static void main(String[] args) {
// 传入 Comparator.reverseOrder() 实现键降序
TreeMap<Integer, String> treeMapDesc = new TreeMap<>(Comparator.reverseOrder());
treeMapDesc.put(3, "苹果");
treeMapDesc.put(1, "香蕉");
treeMapDesc.put(2, "橘子");
System.out.println("TreeMap 按键降序:" + treeMapDesc);
// 输出:{3=苹果, 2=橘子, 1=香蕉}(按键 3→2→1 排序)
}
}示例 2.2:自定义对象作为 TreeMap 的键(需指定比较规则)
比如用 User 对象作为键,按 userId 升序排序:
import java.util.Comparator;
import java.util.TreeMap;
// 自定义 User 类(作为键)
class User {
private int userId;
private String name;
// 构造方法、getter、toString(必须重写,否则打印乱码)
public User(int userId, String name) {
this.userId = userId;
this.name = name;
}
public int getUserId() { return userId; }
@Override
public String toString() { return "User{userId=" + userId + ", name='" + name + "'}"; }
}
public class TreeMapCustomKey {
public static void main(String[] args) {
// 传入 Comparator,指定按 User 的 userId 升序排序
TreeMap<User, String> userMap = new TreeMap<>(Comparator.comparingInt(User::getUserId));
userMap.put(new User(2, "李四"), "部门A");
userMap.put(new User(1, "张三"), "部门B");
userMap.put(new User(3, "王五"), "部门C");
System.out.println("TreeMap 按自定义键(userId)升序:" + userMap);
// 输出:{User{userId=1, name='张三'}=部门B, User{userId=2, name='李四'}=部门A, User{userId=3, name='王五'}=部门C}
}
}3. 方式 3:HashMap/LinkedHashMap 按键排序(转 List 后排序)
HashMap/LinkedHashMap 默认不按键排序,若需按键排序,需先把「键集」转成 List,再用
Collections.sort()排序
import java.util.*;
public class HashMapSortByKey {
public static void main(String[] args) {
// 1. 初始化 HashMap(无序)
HashMap<Integer, String> hashMap = new HashMap<>();
hashMap.put(3, "苹果");
hashMap.put(1, "香蕉");
hashMap.put(2, "橘子");
// 2. 按键排序:步骤
// ① 取出所有键,转成 List
List<Integer> keyList = new ArrayList<>(hashMap.keySet());
// ② 对键 List 排序(升序,默认)
Collections.sort(keyList);
// ③ (可选)降序排序:Collections.sort(keyList, Comparator.reverseOrder());
// 3. 遍历排序后的键,输出结果(保持排序后的顺序)
System.out.println("HashMap 按键升序:");
for (Integer key : keyList) {
System.out.println(key + " → " + hashMap.get(key));
}
// 输出:
// 1 → 香蕉
// 2 → 橘子
// 3 → 苹果
}
}三、按「值」排序的实现方式
按值排序是所有 Map 的通用需求(比如统计词频后按次数排序),核心思路:
把 Map 的键值对(Entry)转成 List,然后通过 Comparator 比较「值」的大小。
通用步骤:
- 取出 Map 中所有的键值对(
entrySet()); - 把 entrySet 转成
List<Map.Entry<K, V>>; - 用
Collections.sort()或List.sort(),传入 Comparator 比较「值」; - (可选)把排序后的 List 转成新的 Map(如 LinkedHashMap,保留排序顺序)。
示例 1:基础类型值(String/Integer)按值升序/降序
以 HashMap 为例(LinkedHashMap 用法完全一致):
import java.util.*;
public class MapSortByValue {
public static void main(String[] args) {
// 1. 初始化 HashMap(键:水果,值:销量)
HashMap<String, Integer> fruitSales = new HashMap<>();
fruitSales.put("苹果", 100);
fruitSales.put("香蕉", 200);
fruitSales.put("橘子", 150);
// 2. 按值排序:步骤
// ① 取出所有键值对,转成 List
List<Map.Entry<String, Integer>> entryList = new ArrayList<>(fruitSales.entrySet());
// ② 按值升序排序(销量从小到大)
entryList.sort(Comparator.comparingInt(Map.Entry::getValue));
System.out.println("按值(销量)升序:");
entryList.forEach(entry -> System.out.println(entry.getKey() + " → " + entry.getValue()));
// 输出:苹果→100,橘子→150,香蕉→200
// ③ 按值降序排序(销量从大到小)
entryList.sort((e1, e2) -> Integer.compare(e2.getValue(), e1.getValue()));
// 简化写法:entryList.sort(Comparator.comparingInt(Map.Entry::getValue).reversed());
System.out.println("\n按值(销量)降序:");
entryList.forEach(entry -> System.out.println(entry.getKey() + " → " + entry.getValue()));
// 输出:香蕉→200,橘子→150,苹果→100
// 3. (可选)转成 LinkedHashMap 保留排序顺序(方便后续使用)
LinkedHashMap<String, Integer> sortedMap = new LinkedHashMap<>();
for (Map.Entry<String, Integer> entry : entryList) {
sortedMap.put(entry.getKey(), entry.getValue());
}
System.out.println("\n排序后的 LinkedHashMap:" + sortedMap);
// 输出:{香蕉=200, 橘子=150, 苹果=100}
}
}示例 2:自定义对象值(如 User)按值排序
比如 Map 的值是 User 对象,按 User 的 age 排序:
import java.util.*;
// 自定义 User 类(作为值)
class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() { return age; }
@Override
public String toString() { return "User{name='" + name + "', age=" + age + "}"; }
}
public class MapSortByCustomValue {
public static void main(String[] args) {
// 1. 初始化 Map(键:编号,值:User 对象)
HashMap<String, User> userMap = new HashMap<>();
userMap.put("001", new User("张三", 25));
userMap.put("002", new User("李四", 20));
userMap.put("003", new User("王五", 30));
// 2. 按 User 的 age 升序排序
List<Map.Entry<String, User>> entryList = new ArrayList<>(userMap.entrySet());
entryList.sort(Comparator.comparingInt(e -> e.getValue().getAge()));
// 3. 输出结果
System.out.println("按值(User.age)升序:");
entryList.forEach(entry -> System.out.println(entry.getKey() + " → " + entry.getValue()));
// 输出:
// 002 → User{name='李四', age=20}
// 001 → User{name='张三', age=25}
// 003 → User{name='王五', age=30}
}
}四、避坑提示(小白必看)
- 键的可比较性:TreeMap 的键必须是可比较的(要么实现 Comparable 接口,要么传入 Comparator),否则会抛
ClassCastException; - 空值问题:HashMap 允许键/值为 null;TreeMap 不允许键为 null(会抛空指针),但允许值为 null;LinkedHashMap 允许键/值为 null;
- 排序后的数据存储:HashMap/LinkedHashMap 排序后,原 Map 顺序不变,排序结果需通过 List 或新的 LinkedHashMap 保存;
- 效率问题:TreeMap 按键排序的时间复杂度是 O(logn)(红黑树特性);HashMap/LinkedHashMap 转 List 排序的时间复杂度是 O(nlogn)(基于快排)
五、总结(小白直接记)
| 需求 | 推荐 Map 类型 | 实现方式 |
|---|---|---|
| 按键自然升序 | TreeMap | 直接使用(无需额外代码) |
| 按键自定义排序(降序/对象键) | TreeMap | 传入 Comparator 接口 |
| HashMap/LinkedHashMap 按键排序 | 任意 | 键集转 List → Collections.sort() |
| 按值排序(任何场景) | 任意 | 键值对(Entry)转成 List →Collections.sort() |
实际开发中:
- 若需长期维护「按键有序」的 Map → 直接用 TreeMap;
- 若只是临时需要按键/值排序 → 用 HashMap + 手动排序(更高效);
- 若需保留排序后的顺序供后续使用 → 排序后转成 LinkedHashMap。
到此这篇关于Java Map排序如何按照值按照键排序的文章就介绍到这了,更多相关java map排序内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
