首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java Map 按 Value 排序完全指南:TreeMap、HashMap、Stream API 多種方案實戰

     編輯:Java 綜合教學

核心結論

  • TreeMap:天然按 Key 排序(紅黑樹),不支持直接按 Value 排序
  • HashMap:無序,需轉換為 List/Stream 排序
  • LinkedHashMap:可保持插入順序或訪問順序,常用於排序後結果收集

方案一:List + Collections.sort()(JDK 7 兼容)

Map map = new HashMap<>();
map.put("apple", 5);
map.put("banana", 3);
map.put("cherry", 20);
map.put("date", 8);

// 1. 轉為 List
List> list = new ArrayList<>(map.entrySet());

// 2. 自定義比較器(按 Value 升序)
list.sort((e1, e2) -> e1.getValue().compareTo(e2.getValue()));
// 或降序:e2.getValue().compareTo(e1.getValue())

// 3. 收集到 LinkedHashMap 保持順序
Map sortedMap = new LinkedHashMap<>();
for (Map.Entry entry : list) {
    sortedMap.put(entry.getKey(), entry.getValue());
}
// 結果:{banana=3, apple=5, date=8, cherry=20}

方案二:Stream API(JDK 8+ 推薦)

按 Value 升序

Map sorted = map.entrySet().stream()
    .sorted(Map.Entry.comparingByValue())  // 升序
    // .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) // 降序
    .collect(Collectors.toMap(
        Map.Entry::getKey,
        Map.Entry::getValue,
        (v1, v2) -> v1,           // 鍵衝突合併策略(Value 不會衝突)
        LinkedHashMap::new        // 保持順序的 Map 實現
    ));

按 Value 降序 + 鍵值對象輸出

List> topList = map.entrySet().stream()
    .sorted(Map.Entry.comparingByValue().reversed())
    .limit(3)  // Top 3
    .collect(Collectors.toList());
// 輸出:[(cherry,20), (date,8), (apple,5)]

方案三:TreeMap 按 Key 排序(復習)

// 自然順序(升序)
Map treeMap = new TreeMap<>(map);

// 自定義 Key 比較器(降序)
Map descMap = new TreeMap<>((k1, k2) -> k2.compareTo(k1));
descMap.putAll(map);

性能與選型建議

方案時間複雜度適用場景JDK 版本
List + sortO(n log n)JDK 7、需兼容舊代碼1.7+
Stream APIO(n log n)現代項目、鏈式操作、並行流1.8+
TreeMap (Key排序)O(log n) 插入需要實時保持 Key 有序1.2+

常見陷阱

  1. 直接用 TreeMap 按 Value 排序:不可行,TreeMap 只按 Key 排序
  2. Collectors.toMap() 不指定 LinkedHashMap:默認返回 HashMap,順序丟失
  3. Value 為 null 導致 NPE:比較器需處理 null,或預先過濾 .filter(e -> e.getValue() != null)
  4. Value 重複導致鍵衝突:toMap 第三參數合併函數必須提供,否則拋異常

完整可運行 Demo

import java.util.*;
import java.util.stream.Collectors;

public class MapValueSortDemo {
    public static void main(String[] args) {
        Map scores = new HashMap<>();
        scores.put("Alice", 88);
        scores.put("Bob", 95);
        scores.put("Charlie", 88);  // 重複 Value
        scores.put("David", 72);
        scores.put("Eve", 91);

        System.out.println("原始: " + scores);

        // Stream 升序
        Map asc = scores.entrySet().stream()
            .sorted(Map.Entry.comparingByValue())
            .collect(Collectors.toMap(
                Map.Entry::getKey, Map.Entry::getValue,
                (v1, v2) -> v1, LinkedHashMap::new));
        System.out.println("升序: " + asc);

        // Stream 降序 Top3
        List> top3 = scores.entrySet().stream()
            .sorted(Map.Entry.comparingByValue().reversed())
            .limit(3)
            .collect(Collectors.toList());
        System.out.println("Top3: " + top3);
    }
}
/* 輸出:
原始: {Alice=88, Bob=95, Charlie=88, David=72, Eve=91}
升序: {David=72, Alice=88, Charlie=88, Eve=91, Bob=95}
Top3: [Bob=95, Eve=91, Alice=88]
*/

總結

  • 現代項目首選 Stream API,代碼簡潔、函數式、易並行
  • 結果收集必須用 LinkedHashMap 保持順序
  • 處理 Value 重複、null 值、大數據量 時注意邊界條件
  • 若需實時按 Value 有序,考慮雙 Map 索引或專用數據結構(如 Guava Multimap)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved