按照大小写敏感的字母顺序对字符串进行简单排序的方法

48
我需要按字母顺序对字符串列表进行排序:
List<String> list = new ArrayList();
list.add("development");
list.add("Development");
list.add("aa");
list.add("AA");
list.add("Aa");

常见的方法是使用比较器:

Collections.sort(list, String.CASE_INSENSITIVE_ORDER);

CaseInsensitiveComparator的问题是“AA”等于“aa”。 对于相同值,字符串出现在结果中的顺序取决于添加的顺序,并且这是不正确的:

"aa","AA","Aa","development","Development"

5
当你写道将“AA”和“aa”视为同一种情况“不正确”时,你对“字母顺序”的确切定义是什么?你的得票最高但尚未被接受的答案表明,您想通过使用“正常”的区分大小写比较来打破平局。为了让您了解在Unicode世界和不同地区设置下,“字母排序”有多复杂,请查看ICU用户指南中关于整理的内容。 - MvG
4个回答

80

如果你不想增加对Guava的依赖(参考Michael的回答),那么这个比较器是等价的:

private static Comparator<String> ALPHABETICAL_ORDER = new Comparator<String>() {
    public int compare(String str1, String str2) {
        int res = String.CASE_INSENSITIVE_ORDER.compare(str1, str2);
        if (res == 0) {
            res = str1.compareTo(str2);
        }
        return res;
    }
};

Collections.sort(list, ALPHABETICAL_ORDER);

我认为这段代码同样易于理解和编写 ...

该方法的最后4行可以更简洁地编写如下:

        return (res != 0) ? res : str1.compareTo(str2);

16

解决这个问题的简单方法是使用Guava的ComparisonChain http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/ComparisonChain.html

private static Comparator<String> stringAlphabeticalComparator = new Comparator<String>() {
        public int compare(String str1, String str2) {
            return ComparisonChain.start().
                                compare(str1,str2, String.CASE_INSENSITIVE_ORDER).
                                compare(str1,str2).
                                result();
         }
 };
Collections.sort(list, stringAlphabeticalComparator);

链中的第一个比较器将根据不区分大小写的顺序对字符串进行排序,第二个比较器将根据不区分大小写的顺序对字符串进行排序。 按照字母顺序,预期的字符串将出现在结果中:

"AA","Aa","aa","Development","development"

2

只需简单使用

java.util.Collections.sort(list)

没有String.CASE_INSENSITIVE_ORDER比较器参数。

1

我最近在这里回答了一个类似的问题。将相同的方法应用于您的问题,将得到以下解决方案:

list.sort(
  p2Ord(stringOrd, stringOrd).comap(new F<String, P2<String, String>>() {
    public P2<String, String> f(String s) {
      return p(s.toLowerCase(), s);
    }
  })
);

问题在于“AA”等于“aa”。对于相同的值,字符串按照添加的顺序出现在结果中,这是不正确的:"aa","AA","Aa","development","Development"您应该使用额外的比较来区分“AA”和“aa”。 - Michael
这是我上面代码的输出:[AA,Aa,aa,Development,development]。与预期相符吗? - missingfaktor
@Michael,请查看链接的答案以了解这个是如何工作的。 - missingfaktor
@Michael,简单来说:p(s.toLowerCase(), s) 的意思是“首先尝试比较小写表示。如果它们相等,则尝试直接比较字符串本身。” - missingfaktor
@Michael,使用Java-8,这段代码将变为list.sortedBy(s -> { Pair.of(s.toLowerCase(), s))sortedBy正在被添加到标准库中。 - missingfaktor
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接