使用java对HashMap数据进行排序

时间:2016-02-02 07:09:58

标签: java

我正在尝试使用以下代码按照排序顺序对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'),那么上面代码打印正确的结果。但是当我在键中使用整数作为字符串类型时,为什么它不起作用?

3 个答案:

答案 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”?同上:110都以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());
}