如何按两个因素对地图进行排序?

时间:2018-04-05 21:57:04

标签: java

我有一张地图,我想按两个因素排序:

1) the int value of each element; and then
2) the length of key of each element.

这个泛型函数可以按值排序,以及如何使它适用于1)和2)的排序?

public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> unsortMap) {

        List<Map.Entry<K, V>> list = new LinkedList<>(unsortMap.entrySet());

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

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

编辑:这个版本不能正常工作。怎么了?

public static Map<String, Integer> sortByValueWithGenerics(Map<String, Integer> unsortMap) {

        List<Map.Entry<String, Integer>> list =
                new LinkedList<Map.Entry<String, Integer>>(unsortMap.entrySet());

        Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
            public int compare(Map.Entry<String, Integer> o1,
                               Map.Entry<String, Integer> o2) {
                int c = (o1.getValue()).compareTo(o2.getValue());


                if (c < 0) {
                    if(o2.getKey().length() >o1.getKey().length()){
                        c=-1;
                    }
                }

                return c;
            }
        });

        Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
        for (Map.Entry<String, Integer> entry : list) {
            sortedMap.put(entry.getKey(), entry.getValue());
        }

        return sortedMap;
    }

1 个答案:

答案 0 :(得分:1)

您的if条件应检查先前的比较是否返回0然后执行以下比较:

if (c == 0) 
   return Integer.compare(o1.getKey().length(), o2.getKey().length());

另外,请注意我已经将o1.getKey().length()作为Integer.compare方法的第一个参数传递,而不是将其作为第二个参数传递给您。

现在,您的比较器读作“按值排序,如果两个给定值相等,则按键升序的长度排序”。

从java-8开始,您可以进一步简化排序逻辑:

list.sort(Map.Entry.<String, Integer>comparingByValue()
                      .thenComparingInt(e -> e.getKey().length());

或者如果你想变得更加漂亮,那么整个方法可以变成:

public static Map<String, Integer> sortByValueThenByKey(Map<String, Integer> unsortMap) {
      return unsortMap.entrySet()
               .stream()
               .sorted(Map.Entry.<String, Integer>comparingByValue()
                       .thenComparingInt(e -> e.getKey().length()))
               .collect(Collectors.toMap(Map.Entry::getKey, 
                     Map.Entry::getValue,(oldValue, newValue) -> newValue, 
                             LinkedHashMap::new));
}