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

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

有没有更简单的方法?


当前回答

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

其他回答

使用通用比较器,例如:

final class MapValueComparator<K,V extends Comparable<V>> implements Comparator<K> {
    private final Map<K,V> map;
    
    private MapValueComparator() {
        super();
    }
    
    public MapValueComparator(Map<K,V> map) {
        this();
        this.map = map;
    }
        
    public int compare(K o1, K o2) {
        return map.get(o1).compareTo(map.get(o2));
    }
}

这可以用java8非常容易地实现

public static LinkedHashMap<Integer, String> sortByValue(HashMap<Integer, String> map) {

        List<Map.Entry<Integer, String>> list = new ArrayList<>(map.entrySet());
        list.sort(Map.Entry.comparingByValue());
        LinkedHashMap<Integer, String> sortedMap = new LinkedHashMap<>();
        list.forEach(e -> sortedMap.put(e.getKey(), e.getValue()));
        return sortedMap;
    }

我合并了user157196和Carter Page的解决方案:

class MapUtil {

    public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue( Map<K, V> map ){
        ValueComparator<K,V> bvc =  new ValueComparator<K,V>(map);
        TreeMap<K,V> sorted_map = new TreeMap<K,V>(bvc);
        sorted_map.putAll(map);
        return sorted_map;
    }

}

class ValueComparator<K, V extends Comparable<? super V>> implements Comparator<K> {

    Map<K, V> base;
    public ValueComparator(Map<K, V> base) {
        this.base = base;
    }

    public int compare(K a, K b) {
        int result = (base.get(a).compareTo(base.get(b)));
        if (result == 0) result=1;
        // returning 0 would merge keys
        return result;
    }
}

迟到。

随着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()

在TreeMap中,键按自然顺序排序。例如,如果您对数字进行排序,(注意4的排序)

{0=0, 10=10, 20=20, 30=30, 4=4, 50=50, 60=60, 70=70}

要解决这个问题,在Java8中,首先检查字符串长度,然后进行比较。

Map<String, String> sortedMap = new TreeMap<>Comparator.comparingInt(String::length)
.thenComparing(Function.identity()));

{0=0, 4=4, 10=10, 20=20, 30=30, 50=50, 60=60, 70=70}