Java Comparator字母数字字符串

时间:2016-12-11 10:57:26

标签: java string comparator

我想实现我的自定义Comparator以这种特殊方式对键映射进行排序:

1
2
3
4
4a
4b
5
6
11
12
12a
...

我不知道怎么能完全做到。我只对数值进行了实例化处理:

aaa = new TreeMap<String, ArrayList<ETrack>>(
    new Comparator<String>()
    {
      @Override
      public int compare(String s1, String s2)
      {
        return Integer.valueOf(s1).compareTo(Integer.valueOf(s2));
      }
    });

但这并不是一个完整的解决方案。有什么想法吗?

4 个答案:

答案 0 :(得分:2)

一种方法是将字符串映射到对象,并让这些对象实现Comparable

你可以做得更简单。如果你喜欢正则表达式,你可以使用这个技巧,即使它不太有效:

// Make sure not to compile the pattern within the method, to spare us some time.
Pattern p = Pattern.compile("^([0-9]+)([a-z]?)$");

/**
 * Converts a string to a sortable integer, ensuring proper ordering:
 * "1" becomes 256
 * "1a" becomes 353
 * "1b" becomes 354
 * "2" becomes 512
 * "100" becomes 25600
 * "100a" becomes 25697
 */
int getSortOrder(String s) {
  Matcher m = p.matcher(s);
  if(!m.matches()) return 0;
  int major = Integer.parseInt(m.group(1));
  int minor = m.group(2).isEmpty() ? 0 : m.group(2).charAt(0);
  return (major << 8) | minor;
}

像这样使用:

new Comparator<String>() {
  @Override
  public int compare(String s1, String s2) {
    return getSortOrder(s1) - getSortOrder(s2);
  }
}

答案 1 :(得分:1)

这是一个单行:

aaa = new TreeMap<String, ArrayList<ETrack>>(Comparators
    .comparingInt(s -> Integer.parseInt(s.replaceAll("\\D", "")))
    .thenComparing(s -> s.replaceAll("\\d", "")));

仅供参考\D匹配非数字,\d匹配数字。

顺便说一句,无论数字和非数字部分的顺序如何,这都会有效。

答案 2 :(得分:0)

如果你只有一个字母而不是更多, 你可以尝试这样的事情:

  aaa = new TreeMap<String, ArrayList<ETrack>>(
  new Comparator<String>()
  {
  @Override
  public int compare(String s1, String s2)
  {
     String newS1=s1;
     String newS2=s2;
     char s1Letter=0;
     char s1Letter=0;
     //checks if last char is not a digit by ascii
    if(!(s1.charAt(s1.length()-1)>=48 && s1.charAt(s1.length()-1)<=57)){
        newS1 = s1.substring(0,s1.length()-1);
        s1Letter = s1.charAt(s1.length()-1);
   }
      if(!(s2.charAt(s2.length()-1)>=48 && s2.charAt(s2.length()-1)<=57)){
        newS2 = s2.substring(0,s2.length()-1);
        s2Letter = s2.charAt(s2.length()-1);
   }
   int s1Val = Integer.parseInt(newS1);
   int s2Val = Integer.parseInt(newS2);
   if(s1Val<s2Val)
      return -1;
   else if(s1Val>s2Val)
      return 1;
   else if(s1Letter > s2Letter)
      return 1;
   else if(s1Letter < s2Letter)
      return -1;
   else
      retrurn 0;

  }
});

希望有帮助:) 可能有一个更优雅的解决方案,但我相信如果我理解你所面临的问题,这将对你有用

答案 3 :(得分:0)

@bohemian答案很棒,我只做了以下更改,因此几乎可以在任何地方使用。检查数字字符串是因为如果您的输入字符串中没有任何数字,您将收到错误。

Startup.Configure()

请注意,StringUtils来自Program.Main()