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

时间:2016-04-30 13:14:17

标签: java sorting key 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");

第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);
      }
    });

但这没有帮助。

2 个答案:

答案 0 :(得分:0)

您可以使用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 = My First String,Tier 2 = My First String,Tier 3 = My First String,Tier 10 = My Last String}

答案 1 :(得分:0)

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

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;
   }