Simple way to sort strings in the (case sensitive) alphabetical order
Asked Answered
S

4

49

I need to sort list of strings in the alphabetical order:

List<String> list = new ArrayList();
list.add("development");
list.add("Development");
list.add("aa");
list.add("AA");
list.add("Aa");

A common way to do it is to use comparator:

Collections.sort(list, String.CASE_INSENSITIVE_ORDER);

The problem of the CaseInsensitiveComparator that “AA” is equals to “aa”. Strings appear in the result according to the order of adding for the same values, and it is not correct:

"aa","AA","Aa","development","Development"
Schuyler answered 24/6, 2012 at 9:7 Comment(1)
When you write that treating "AA" and "aa" the same “is not correct”, then what is your exact definition of “alphabetical order”? Your top-voted but yet unaccepted answer suggests that you want to break ties by using the “normal” case-sensitive comparison. To give you an idea of how complex “alphabetical sorting” is in the unicode world and with different locales, have a look at what the ICU User Guide writes about collation.Beitnes
E
81

If you don't want to add a dependency on Guava (per Michael's answer) then this comparator is equivalent:

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

And I think it is just as easy to understand and code ...

The last 4 lines of the method can written more concisely as follows:

        return (res != 0) ? res : str1.compareTo(str2);
Esprit answered 24/6, 2012 at 9:40 Comment(0)
S
16

The simple way to solve the problem is to use ComparisonChain from Guava 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);

The first comparator from the chain will sort strings according to the case insensitive order, and the second comparator will sort strings according to the case insensitive order. As excepted strings appear in the result according to the alphabetical order:

"AA","Aa","aa","Development","development"
Schuyler answered 24/6, 2012 at 9:7 Comment(0)
C
2

Simply use

java.util.Collections.sort(list)

without String.CASE_INSENSITIVE_ORDER comparator parameter.

Crevice answered 1/10, 2013 at 11:59 Comment(0)
C
1

I recently answered a similar question here. Applying the same approach to your problem would yield following solution:

list.sort(
  p2Ord(stringOrd, stringOrd).comap(new F<String, P2<String, String>>() {
    public P2<String, String> f(String s) {
      return p(s.toLowerCase(), s);
    }
  })
);
Christensen answered 24/6, 2012 at 10:54 Comment(10)
The problem is that “AA” is equals to “aa”. Strings appear in the result according to the order of adding for the same values, and it is not correct: "aa","AA","Aa","development","Development" You should use additional compare to distinguish "AA" and "aa".Schuyler
Here is the output of my above code: [AA, Aa, aa, Development, development]. Matches what's expected?Christensen
@Michael, please see the linked answer to understand how this works.Christensen
@Michael, in simple terms: p(s.toLowerCase(), s) says "first try comparing the lower case representations. If they turn out to be equal, try direct comparing strings themselves."Christensen
Thanks! Any case, suggestion provided by Stephen is simpler and readable :)Schuyler
I'd say it's easier, not simpler. ;-)Christensen
@Michael, with Java-8, this code would become list.sortedBy(s -> { Pair.of(s.toLowerCase(), s)). sortedBy is being added to the standard library.Christensen
@Christensen - Simplicity (like beauty) is in the eye of the beholder. What is simple to you is not necessarily simple to other people, and vice versa.Esprit
While true, in this context, it's a blanket statement. Please see the talk I linked to know how simplicity (or some aspects thereof) can be objective.Christensen
Going around downvoting answers? Good. Carry on.Christensen

© 2022 - 2024 — McMap. All rights reserved.