Java:如何使用通用键和值对HashMap的值进行排序?

时间:2014-07-11 08:57:33

标签: java generics comparator comparable

我有一个TreeMap,我需要按值排序。如果值是Integer类型,我可以对Map进行排序。

public class MapSorting {

    public static Map<String, Integer> sortByValues(Map<String, Integer> tempMap) {

        ValueComparator bvc = new ValueComparator(tempMap);
        Map<String, Integer> sortedMap = new TreeMap<String, Integer>(bvc);
        sortedMap.putAll(tempMap);
        return sortedMap;

    }
}


class ValueComparator implements Comparator<String> {

        Map<String, Integer> base;

        public ValueComparator(Map<String, Integer> base) {
            this.base = base;
        }

        public int compare(String a, String b) {
            if (base.get(a) >= base.get(b)) {
                return -1;
            } else {
                return 1;
            }
        }
    }

但是我如何使方法通用?我希望能够将具有键和任何类型的值的Map发送到此方法。

我想返回一个基于值排序的TreeMap。

有人可以帮忙吗?

2 个答案:

答案 0 :(得分:2)

注意TreeMap旨在按键排序,而不是按值排序。这让我觉得您应该使用其他数据结构来存储您的结果:例如List<Entry<K, V>>

注意:我强烈反对使用这段代码,因为我觉得它是一种反模式。我这样做只是为了表明它是如何可能的。

那就是说,我这样做了(至少需要Java 8或改编代码):

public static <K, V extends Comparable> Map<K, V> sortByValues(Map<K, V> tempMap) {
  TreeMap<K, V> map = new TreeMap<>(buildComparator(tempMap));
  map.putAll(tempMap);
  return map;
}

public static <K, V extends Comparable> Comparator<? super K> buildComparator(final Map<K, V> tempMap) {
  return (o1, o2) -> tempMap.get(o1).compareTo(tempMap.get(o2));
}

测试:

Map<Integer, String> map = new HashMap<>();
map.put(1, "B");
map.put(2, "C");
map.put(3, "A");

for(Map.Entry<Integer, String> entry : sortByValues(map).entrySet()) {
  System.out.println(entry.getKey()+" : "+ entry.getValue());
}

输出:

3 : A
1 : B
2 : C

注意:我没有处理空案例,因为这对于这个解释并不重要。

答案 1 :(得分:0)

您可以创建一个比较Comparable的值的比较器:

class ValueComparator<Comparable> implements Comparator<Comparable> {

    Map<String, Comparable> base;

    public ValueComparator(Map<String, Comparable> base) {
        this.base = base;
    }

    public int compare(Comparable a, Comparable b) {
        return a.compareTo(b);
    }
}