Java基础 —— 根据 Key 或是 Value 对 Map 进行排序

how to sort Map values by key in Java

https://stackoverflow.com/questions/922528/how-to-sort-map-values-by-key-in-java

Sort a Map<Key, Value> by values (Java)

https://stackoverflow.com/questions/109383/sort-a-mapkey-value-by-values-java


根据 Key 对 Map 进行排序

package com.practice.map;

import java.util.*;

public class SortedMapByKey {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("abc", 122);
        map.put("bsh", 232);
        map.put("dsa", 12);
        map.put("aac", 192);

        System.out.println("未对 Key 进行排序:");
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            System.out.println("\"" + entry.getKey() + "\"" + " : " + entry.getValue());
        }

        System.out.println("-----------------------------");

        System.out.println("使用 Collections.sort 对 Key 进行排序:");
        List<String> sortedKeys = new ArrayList(map.keySet());
        Collections.sort(sortedKeys);
        for (String key : sortedKeys){
            System.out.println("\"" + key + "\"" + " : " + map.get(key));
        }

        System.out.println("-----------------------------");

        System.out.println("使用 TreeMap 对 Key 进行排序:");
        Map<String, Integer> treeMap = new TreeMap<>(map);
        for (Map.Entry<String, Integer> entry : treeMap.entrySet()) {
            System.out.println("\"" + entry.getKey() + "\"" + " : " + entry.getValue());
        }
    }
}
未对 Key 进行排序:
"aac" : 192
"abc" : 122
"dsa" : 12
"bsh" : 232
-----------------------------
使用 Collections.sort 对 Key 进行排序:
"aac" : 192
"abc" : 122
"bsh" : 232
"dsa" : 12
-----------------------------
使用 TreeMap 对 Key 进行排序:
"aac" : 192
"abc" : 122
"bsh" : 232
"dsa" : 12

Process finished with exit code 0

根据 Value 对 Map 进行排序

Here’s a generic-friendly version you’re free to use:

import java.util.*;

public class MapUtil {
    public static <K, V extends Comparable<? super V>> Map<K, V> 
        sortByValue(Map<K, V> map) {
        List<Map.Entry<K, V>> list = new LinkedList<Map.Entry<K, V>>(map.entrySet());
        Collections.sort( list, new Comparator<Map.Entry<K, V>>() {
            public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) {
                return (o1.getValue()).compareTo( o2.getValue() );
            }
        });

        Map<K, V> result = new LinkedHashMap<K, V>();
        for (Map.Entry<K, V> entry : list) {
            result.put(entry.getKey(), entry.getValue());
        }
        return result;
    }
}

And an associated JUnit4 test so you don’t have to take my word for it:

import java.util.*;
import org.junit.*;

public class MapUtilTest {
    @Test
    public void testSortByValue() {
        Random random = new Random(System.currentTimeMillis());
        Map<String, Integer> testMap = new HashMap<String, Integer>(1000);
        for(int i = 0; i < 1000; ++i) {
            testMap.put( "SomeString" + random.nextInt(), random.nextInt());
        }

        testMap = MapUtil.sortByValue(testMap);
        Assert.assertEquals(1000, testMap.size());

        Integer previous = null;
        for(Map.Entry<String, Integer> entry : testMap.entrySet()) {
            Assert.assertNotNull(entry.getValue());
            if (previous != null) {
                Assert.assertTrue(entry.getValue() >= previous);
            }
            previous = entry.getValue();
        }
    }
}

Java 7 Version

public static <K, V extends Comparable<? super V>> Map<K, V> 
    sortByValue(Map<K, V> map) {
    List<Map.Entry<K, V>> list = new LinkedList<>(map.entrySet());
    Collections.sort( list, new Comparator<Map.Entry<K, V>>() {
        @Override
        public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) {
            return (o1.getValue()).compareTo(o2.getValue());
        }
    });

    Map<K, V> result = new LinkedHashMap<>();
    for (Map.Entry<K, V> entry : list) {
        result.put(entry.getKey(), entry.getValue());
    }
    return result;
}

Java 8 Version. This will sort according to the value in ascending order; for descending order, it is just possible to uncomment the call to Collections.reverseOrder().

public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {
    return map.entrySet()
              .stream()
              .sorted(Map.Entry.comparingByValue(/*Collections.reverseOrder()*/))
              .collect(Collectors.toMap(
                Map.Entry::getKey, 
                Map.Entry::getValue, 
                (e1, e2) -> e1, 
                LinkedHashMap::new
              ));
}

There is one more technique to sort HashMap by Values. Here, no Comparator is used. We do sort based on Keys, swap keys and values, sort based on values and again swap to get the finalMap, which is sorted HashMap based on Values.

 private static LinkedHashMap<String, String> method1(HashMap<String, String> originalHashMap) {
        LinkedHashMap<String, String> sortedHashMapByKeys = new LinkedHashMap<>(); //maintains the order of putting
        TreeMap<String, String> originalTreeMap = new TreeMap<>(originalHashMap); //sorts based on keys
        for (Map.Entry<String, String> map: originalTreeMap.entrySet()) {
            sortedHashMapByKeys.put(map.getKey(), map.getValue());
        }

        LinkedHashMap<String, String> reversedOfSortedLinkedHashMap = new LinkedHashMap<>();
        for (Map.Entry<String, String> map: sortedHashMapByKeys.entrySet()) {
            reversedOfSortedLinkedHashMap.put(map.getValue(), map.getKey());
        }

        LinkedHashMap<String, String> finalMap = new LinkedHashMap<>();
        TreeMap<String, String> treeMapOfReversedOfSortedLinkedHashMap = new TreeMap<>(reversedOfSortedLinkedHashMap);
        for (Map.Entry<String, String> map: treeMapOfReversedOfSortedLinkedHashMap.entrySet()) {
            finalMap.put(map.getKey(), map.getValue()); //sort and swap
        }
        return finalMap;
    }

### Java Map按键或值排序的方法及实现 #### 使用 `TreeMap` 实现按键排序 当需要按键对 `Map` 中的键值对进行排序时,可以通过使用 `TreeMap` 来完成。`TreeMap` 是一种基于红黑树的数据结构,默认会按照键的自然顺序进行排序。如果希望自定义排序方式,则可以在创建 `TreeMap` 的时候通过构造函数传递一个自定义的比较器。 以下是具体代码示例: ```java import java.util.Map; import java.util.TreeMap; public class Main { public static void main(String[] args) { Map<String, Integer> unsortedMap = Map.of("b", 2, "a", 1, "c", 3); // 创建带有默认自然顺序的 TreeMap Map<String, Integer> sortedByKeysNaturalOrder = new TreeMap<>(unsortedMap); System.out.println(sortedByKeysNaturalOrder); // 输出 {a=1, b=2, c=3} // 自定义 Comparator 排序 Map<String, Integer> sortedByCustomComparator = new TreeMap<>((k1, k2) -> k2.compareTo(k1)); sortedByCustomComparator.putAll(unsortedMap); System.out.println(sortedByCustomComparator); // 输出 {c=3, b=2, a=1} } } ``` 上述代码展示了两种情况:一是利用 `TreeMap` 默认的自然顺序;二是通过提供自定义比较器来改变排序逻辑[^2]。 --- #### 使用 `Stream API` 对 Map 按键或值排序 对于更灵活的需求,比如按值排序或者保留原始数据结构不变的情况下获取排序后的结果,可以借助 Java 8 提供的 `Stream API` 完成此操作。 ##### 按键排序 下面展示了一个按键升序排列的例子: ```java import java.util.*; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { Map<String, Integer> map = new HashMap<>(); map.put("banana", 5); map.put("apple", 3); map.put("orange", 7); // 按照 key 升序排序并转换回 LinkedHashMap Map<String, Integer> resultByKeyAsc = map.entrySet() .stream() .sorted(Map.Entry.comparingByKey()) // 比较 Key [^1] .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); System.out.println(resultByKeyAsc); // 输出 {apple=3, banana=5, orange=7} } } ``` 此处的关键在于调用了 `Map.Entry.comparingByKey()` 方法作为流式排序的标准。 --- ##### 按值降序排序 同样地,也可以轻松调整为按值排序的方式。这里给出的是按值降序的一个例子: ```java import java.util.*; public class Main { public static void main(String[] args) { Map<String, Integer> map = new HashMap<>(); map.put("banana", 5); map.put("apple", 3); map.put("orange", 7); // 按照 value 降序排序 List<Map.Entry<String, Integer>> list = new ArrayList<>(map.entrySet()); list.sort((o1, o2) -> o2.getValue().compareTo(o1.getValue())); // 转换回 Map Map<String, Integer> resultMap = new LinkedHashMap<>(); for (Map.Entry<String, Integer> entry : list) { resultMap.put(entry.getKey(), entry.getValue()); } System.out.println(resultMap); // 输出 {orange=7, banana=5, apple=3} } } ``` 在这个版本中,我们先将 `entrySet` 转化成了列表形式以便于手动指定排序规则,再将其重新组装到一个新的有序映射里去[^4]。 --- #### 处理键冲突的情况 有时可能会遇到这样的场景——两个不同的键对应相同的值,在这种情况下就需要决定如何处理这些重复项。这通常涉及到更新策略的选择。例如,可以选择累加旧值与新值得到最终的结果。下面是这样一个简单的实例演示: ```java import java.util.HashMap; public class Main { public static void main(String[] args) { String key = "sameKey"; HashMap<String, Integer> map = new HashMap<>() {{ put(key, 10); }}; // 合并相同键对应的数值 map.merge(key, 5, (oldValue, newValue) -> oldValue + newValue); System.out.println(map.get(key)); // 输出 15 } } ``` 在此处应用了 `merge` 函数,并指定了在发现已有条目存在时应执行的操作[(oldVal, newVal) -> oldVal + newVal][^5]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值