如何在TreeMap中使用字母数字对键进行排序



我有以下TreeMap:

Map<String, Map<String, String>> result = new TreeMap<String, Map<String, String>>();            
result.put("Tier 1",  "My First String", "My First String ABC");
result.put("Tier 2",  "My First String", "My First String DEF");
result.put("Tier 3",  "My First String", "My First String DDD");
result.put("Tier 10", "My Last String", "My First String TTT");

打印出的结果不符合"Tier 10"String:的顺序

Tier 1,  My First String, My First String ABC
Tier 10, My First String, My First String TTT
Tier 2,  My First String, My First String DEF
Tier 3,  My First String, My First String DDD

我希望它按逻辑顺序排列:

Tier 1,  My First String, My First String ABC
Tier 2,  My First String, My First String DEF
Tier 3,  My First String, My First String DDD
Tier 10, My First String, My First String TTT

我尝试使用Comparator如下:

Map<String, Map<String, String>> result = new TreeMap<String, Map<String, String>>(
    new Comparator<String>() {
      @Override
      public int compare(String o1, String o2) {
        return o1.compareTo(o2);
      }
    });

但这无济于事。

您可以使用lambda表达式轻松定义Comparator:

TreeMap<String, String> result = new TreeMap<String, String>((String s1, String s2) -> {
    Matcher m1 = Pattern.compile("\d+").matcher(s1);
    Matcher m2 = Pattern.compile("\d+").matcher(s2);
    m1.find();
    m2.find();
    return Integer.compare(Integer.parseInt(m1.group()), Integer.parseInt(m2.group()));
});
result.put("Tier 3",  "My First String");
result.put("Tier 10", "My Last String");
result.put("Tier 1",  "My First String");
result.put("Tier 2",  "My First String");
System.out.println(result);

输出:

{Tier 1=我的第一个字符串,Tier 2=我的首个字符串,Tier 3=我的首条字符串,Tier 10=我的最后一个字符串}

这就是我现在拥有的,而且效果很好:(在这里回答了我自己的问题)

Map<String, Map<String, String>> result = new TreeMap<String, Map<String, String>>(
    new Comparator<String>() {
      @Override
      public int compare(String s1, String s2) {
        Integer i1 = null;
        Integer i2 = null;
        int retVal = 99;
        if (containsDigit(s1) && containsDigit(s2) && (extractString(s1).equals(extractString(s2)))) {
          i1 = new Integer(extractNumber(s1));
          i2 = new Integer(extractNumber(s2));
          if (i1 != null && i2 != null) {
            retVal = i1.compareTo(i2);
          }
        } else {
          retVal = s1.compareTo(s2);
        }
        return retVal;
      }
    });

其他支持的方法:

private String extractNumber(final String str) {
    if (str == null || str.isEmpty()) {
        return emptyString_;
    }
    return str.replaceAll("\p{Alpha}", emptyString_).trim();
   }
private String extractString(final String str) {
    if (str == null || str.isEmpty()) {
      return emptyString_;
    }
    return str.replaceAll("[^a-zA-Z]", emptyString_);
}
private boolean containsDigit(String s) {
    boolean found = false;
    if (s != null && !s.isEmpty()) {
      for (char c : s.toCharArray()) {
        if (Character.isDigit(c)) {
           found = true;
           break;
        }
      }
    }
     return found;
   }

最新更新