排序Hashmap值compareTo方法

时间:2017-12-20 02:34:29

标签: java collections hashmap

我正在编写以下代码来对哈希映射值进行排序:

private static HashMap sortByValues(HashMap map) { 
    List list = new LinkedList(map.entrySet());
    Collections.sort(list, new Comparator() {
        public int compare(Object o1, Object o2) {
            return (((Map.Entry) (o1)).getValue()).compareTo(((Map.Entry) (o2)).getValue());
        }
    });
}

然而,当我执行此操作时,它会抛出错误,指出无法找到符号compareTo。但是在lang包中的String类中的方法不是吗?

此外,当我通过添加可比较的类型转换来替换它时,它运行良好

private static HashMap sortByValues(HashMap map) { 
    List list = new LinkedList(map.entrySet());
    Collections.sort(list, new Comparator() {
        public int compare(Object o1, Object o2) {
             return ((Comparable) ((Map.Entry) (o1)).getValue()).compareTo(((Map.Entry) (o2)).getValue());
        }
    });
}

有人可以帮忙,我是收藏中的初学者。

3 个答案:

答案 0 :(得分:2)

所有Java的集合类和接口都是泛型,这意味着它们旨在与类型参数一起使用。由于历史原因,可以在没有类型参数的情况下使用它们,这就是您在此处所做的。但是,这样做是个坏主意,因为

  • 你牺牲了编译器给你的很多类型安全性,
  • 您最终会将对象转换为您需要的任何类型,这很容易出错,而且这些错误通常只会在运行时显示出来。

在编译时查找错误比在运行时查找错误要好。编译器是您的朋友 - 它会为您提供消息以帮助您找到错误。

现在,在这种特殊情况下,您似乎正在构建地图中值的排序列表。但是,如果地图中的值属于可以排序的某种类型,那么这样做才有意义。排序Object没有一般方法,所以为了理所当然,你想要将你的参数限制为一个可以对其值进行排序的地图,或者换句话说,可以将其与其他对象进行比较。同类型。

通用接口告诉您一个对象可以与另一个对象进行比较Comparable。因此,如果您有类型V,那么编写V extends Comparable<V>意味着可以使用{{1}将V类型的一个对象与V类型的其他对象进行比较} 方法。这是您希望地图中值的类型遵守的条件。地图中的键类型不需要任何此类条件。

因此,您可以将您的方法编写为泛型,这意味着它的签名将在compareTo个字符内列出一些类型参数,可能在这些类型参数上有一些条件。在你的情况下,你会给你的方法一个这样的签名,假设它将返回< >

List

当然,如果你真的打算返回某种有序的地图,那么它可能更像是

private static <K, V extends Comparable<V>> List<V> sortAndListValues(Map<K,V> map)

但您需要记住,无法对private static <K, V extends Comparable<V>> Map<K,V> sortByValues(Map<K,V> map) 个对象进行排序。它们按照密钥类的HashMap函数以及映射的当前大小隐含的顺序自然排序。这通常不是一个非常有用的订单。 JDK中还有其他类型的映射,例如

  • hashCode,根据密钥对其条目进行排序 - 而不是您想要的
  • TreeMap,根据插入的顺序对其条目进行排序 - 您可以在这里使用它。

为了回答你的问题,我只想写你方法的LinkedHashMap版本。

List

请注意,通过在适当的地方使用类型参数private static <K, V extends Comparable<V>> List<V> sortAndListValues(Map<K,V> map) { List<V> toReturn = new LinkedList<>(map.values()); Collections.sort(toReturn, new Comparator<V>() { public int compare(V first, V second) { return first.compareTo(second); } }); return toReturn; } K,不需要任何类型的转换。如果您尝试以不适合其类型的方式使用地图中的任何对象,编译器也会发出警告。

使用Java 8附带的“功能样式”当然有更短的编写方式。但这完全是另一篇文章的主题。

答案 1 :(得分:1)

@ghostrider - 您已从HashMap中删除了泛型,因此键和值都是Object类型。 map的内部内容是Comparable类型,但引用的是Entry<Object, Object>而不是Entry<Object, Comparable>。请看下面的例子。

Object obj = new Integer(5);
int i = obj.intValue();  // Error
int i = ((Integer)obj).intValue(); // Success

此处int i = obj.intValue();失败,但int i = ((Integer)obj).intValue();获得成功,因为我是显式类型转换,因为引用属于对象类型。

答案 2 :(得分:-2)

您可以按照

执行此操作
private static Map<String, Integer> sortByValue(Map<String, Integer> unsortMap) {

        // 1. Convert Map to List of Map
        List<Map.Entry<String, Integer>> list =
                new LinkedList<Map.Entry<String, Integer>>(unsortMap.entrySet());

        // 2. Sort list with Collections.sort(), provide a custom Comparator
        //    Try switch the o1 o2 position for a different order
        Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
            public int compare(Map.Entry<String, Integer> o1,
                               Map.Entry<String, Integer> o2) {
                return (o1.getValue()).compareTo(o2.getValue());
            }
        });

        // 3. Loop the sorted list and put it into a new insertion order Map LinkedHashMap
        Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
        for (Map.Entry<String, Integer> entry : list) {
            sortedMap.put(entry.getKey(), entry.getValue());
        }




        return sortedMap;
    }