我正在编写以下代码来对哈希映射值进行排序:
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());
}
});
}
有人可以帮忙,我是收藏中的初学者。
答案 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;
}