我正在尝试使用以下代码按照排序顺序对HashMap数据进行排序:
public static void main(String[] args) {
Map<String, String> unsortMap = new HashMap<String, String>();
unsortMap.put("10", "z");
unsortMap.put("5", "b");
unsortMap.put("6", "a");
unsortMap.put("20", "c");
unsortMap.put("1", "d");
unsortMap.put("7", "e");
unsortMap.put("8", "y");
unsortMap.put("99", "n");
unsortMap.put("50", "j");
unsortMap.put("2", "m");
unsortMap.put("9", "f");
System.out.println("Unsort Map......");
printMap(unsortMap);
System.out.println("\nSorted Map......");
Map<String, String> treeMap = new TreeMap<String, String>(unsortMap);
printMap(treeMap);
}
public static void printMap(Map<String, String> map) {
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println("Key : " + entry.getKey()
+ " Value : " + entry.getValue());
}
}
该计划的输出:
Sorted Map......
Key : 1 Value : d
Key : 10 Value : z
Key : 2 Value : m
Key : 20 Value : c
Key : 5 Value : b
Key : 50 Value : j
Key : 6 Value : a
Key : 7 Value : e
Key : 8 Value : y
Key : 9 Value : f
Key : 99 Value : n
预期产出:
Sorted Map......
Key : 1 Value : d
Key : 2 Value : m
Key : 5 Value : b
Key : 6 Value : a
Key : 7 Value : e
Key : 8 Value : y
Key : 9 Value : f
Key : 10 Value : z
Key : 20 Value : c
Key : 50 Value : j
Key : 99 Value : n
我知道如果我在数字上使用字符(例如1代表'A',2代表'C',.. 99代表'E'),那么上面代码打印正确的结果。但是当我在键中使用整数作为字符串类型时,为什么它不起作用?
答案 0 :(得分:4)
密钥类型为String
,因此值将按字典顺序存储并比较为字符串。单个字符串从左到右进行比较,而不是数值。你得到的输出是排序字符串的正确输出。
如果希望将值作为整数进行比较,可以将通用参数定义为<Integer,String>
,或者为TreeMap
实现一个新的比较器,将字符串转换为整数进行比较。
这是一个示例比较器
public static class StringAsNumberComparator implements Comparator<String>
{
public static class StringAsNumberComparator implements Comparator<String>
{
@Override
public int compare(String o1, String o2)
{
/*
* A string compares equal to itself, and two null values are also equal.
* Note that we *really DO* want to use reference comparison here instead of String.equals().
* This is an optimization to detect a string being compared to itself (not another string
* that happens to contain the same value).
*/
if (o1 == o2) return 0; // A string compares equal to itself
/*
* Also we DO NOT do this:
*
* if (o1 != null && o2 != null && o1.equals(o2)) return 0;
*
* with the goal of detecting equal-valued because we want all strings to go
* through the conversion below, where null and invalid numbers are detected
* and mapped to Integer.MIN_VALUE so they'll sort to the front.
*/
int temp1, temp2;
/*
* Convert the first string into a number for comparison.
* If the first string is null or not a valid number make it sort to the beginning
*/
try {
temp1 = o1==null ? Integer.MIN_VALUE : Integer.parseInt(o1);
} catch (NumberFormatException nx) {
temp1 = Integer.MIN_VALUE;
}
/*
* Convert the second string into a number for comparison.
* If the second string is null or not a valid number make it sort to the beginning
*/
try {
temp2 = o2==null ? Integer.MIN_VALUE : Integer.parseInt(o2);
} catch (NumberFormatException nx) {
temp2 = Integer.MIN_VALUE;
}
/*
* Do the actual comparison
*/
return Integer.compare(temp1, temp2);
}
}
您需要修改代码,如下所示
System.out.println("\nSorted Map......");
Map<String, String> treeMap = new TreeMap<>(new StringAsNumberComparator()); // <=== different constructor to set Comparator
treeMap.putAll(unsortMap); // <=== Here's where you copy the elements in
printMap(treeMap);
一个可能的增强功能是参数化比较器,这样你就可以给它使用无效或空字符串的值,使它们排序到开头(Integer.MIN_VALUE
)或结束(Integer.MAX_VALUE
) 。我会把它留作练习。
答案 1 :(得分:2)
它正在发挥作用,而不是你想要的方式。字符串按字典顺序进行比较,而不是数字。看看字典:订单是“A”,“Aardvark”,“B” - 还是“A”,“B”,“Aardvark”?同上:1
和10
都以1
开头,所以它们在一起;由于1
是[{1}}的前缀,10
之前就是。
答案 2 :(得分:0)
使用此代码
Map<Integer, String> map = new TreeMap<Integer, String>(unsortMap);
System.out.println("After Sorting:");
Set set2 = map.entrySet();
Iterator iterator2 = set2.iterator();
while(iterator2.hasNext()) {
Map.Entry me2 = (Map.Entry)iterator2.next();
System.out.print(me2.getKey() + ": ");
System.out.println(me2.getValue());
}