我对Java比较陌生,经常发现需要对值进行Map<Key,Value>排序。

由于这些值不是唯一的,我发现自己将keySet转换为一个数组,并使用自定义比较器通过数组排序对该数组进行排序,该比较器根据与该键关联的值进行排序。

有没有更简单的方法?


当前回答

因为地图是无序的要对其进行排序,我们可以执行以下操作

Map<String, String> map= new TreeMap<String, String>(unsortMap);

您应该注意,与哈希映射不同,树映射保证其元素将按升序键排序。

其他回答

最好的方法是将HashMap转换为TreeMap。TreeMap自己排序键。如果您希望对值进行排序,则可以快速修复,如果您的值不重复,则可以使用键切换值。

我重写了devinmore的方法,该方法在不使用迭代器的情况下,根据地图的值对其进行排序:

public static Map<K, V> sortMapByValue(Map<K, V> inputMap) {

    Set<Entry<K, V>> set = inputMap.entrySet();
    List<Entry<K, V>> list = new ArrayList<Entry<K, V>>(set);

    Collections.sort(list, new Comparator<Map.Entry<K, V>>()
    {
        @Override
        public int compare(Entry<K, V> o1, Entry<K, V> o2) {
            return (o1.getValue()).compareTo( o2.getValue() );  //Ascending order
        }
    } );

    Map<K, V> sortedMap = new LinkedHashMap<>();

    for(Map.Entry<K, V> entry : list){
        sortedMap.put(entry.getKey(), entry.getValue());
    }

    return sortedMap;
}

注意:我们使用LinkedHashMap作为输出映射,因为我们的列表已经按值排序,现在我们应该按照插入键值的顺序将列表存储到输出映射中。因此,如果您使用例如TreeMap作为输出地图,您的地图将再次按地图键排序!

这是主要方法:

public static void main(String[] args) {
    Map<String, String> map = new HashMap<>();
    map.put("3", "three");
    map.put("1", "one");
    map.put("5", "five");
    System.out.println("Input Map:" + map);
    System.out.println("Sorted Map:" + sortMapByValue(map));
}

最后,这是输出:

Input Map:{1=one, 3=three, 5=five}
Sorted Map:{5=five, 1=one, 3=three}

使用Guava库:

public static <K,V extends Comparable<V>>SortedMap<K,V> sortByValue(Map<K,V> original){
    var comparator = Ordering.natural()
            .reverse() // highest first
            .nullsLast()
            .onResultOf(Functions.forMap(original, null))
            .compound(Ordering.usingToString());
    return ImmutableSortedMap.copyOf(original, comparator);
}

迟到。

随着Java-8的出现,我们可以以非常简单/简洁的方式使用流进行数据操作。您可以使用流按值对映射条目进行排序,并创建一个LinkedHashMap,以保留插入顺序迭代。

Eg:

LinkedHashMap sortedByValueMap = map.entrySet().stream()
                .sorted(comparing(Entry<Key,Value>::getValue).thenComparing(Entry::getKey))     //first sorting by Value, then sorting by Key(entries with same value)
                .collect(LinkedHashMap::new,(map,entry) -> map.put(entry.getKey(),entry.getValue()),LinkedHashMap::putAll);

对于反向排序,请替换:

comparing(Entry<Key,Value>::getValue).thenComparing(Entry::getKey)

with

comparing(Entry<Key,Value>::getValue).thenComparing(Entry::getKey).reversed()

给定的地图

   Map<String, Integer> wordCounts = new HashMap<>();
    wordCounts.put("USA", 100);
    wordCounts.put("jobs", 200);
    wordCounts.put("software", 50);
    wordCounts.put("technology", 70);
    wordCounts.put("opportunity", 200);

根据值按升序对地图进行排序

Map<String,Integer>  sortedMap =  wordCounts.entrySet().
                                                stream().
                                                sorted(Map.Entry.comparingByValue()).
        collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
    System.out.println(sortedMap);
    

根据值按降序排序地图

Map<String,Integer>  sortedMapReverseOrder =  wordCounts.entrySet().
            stream().
            sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).
            collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
    System.out.println(sortedMapReverseOrder);

输出:

{软件=50,技术=70,美国=100,工作=200,机会=200}

{工作岗位=200,机会=200,美国=100,技术=70,软件=50}