Please note: I mention JUnit here and provide a SSCCE code example using it but this is a Java collections question at heart and can be answered by anyone with Java experience regardless of their experience with JUnit.
Java 8 here and I am trying to sort a list of strings but am getting some unexpected behaviors out of Collections.sort(myList) and am wondering what is happening.
Here is my full unit test:
@RunWith(MockitoJUnitRunner.class)
public class SorterTest {
@Test
public void should_sort_correctly_including_capitalization_rules() {
// given
String[] actualNames = new String[] {
"DCME",
"CCME",
"ACME",
"BCME",
"AGME",
"AACME",
"aCME",
"Acme",
"AaCME",
"aACME",
};
List<String> actual = Arrays.asList(actualNames);
// the order I would *expect* them to sort into...
String[] expectedNames = new String[] {
"aACME",
"aCME",
"AaCME",
"AACME",
"Acme",
"ACME",
"AGME",
"BCME",
"CCME",
"DCME"
};
List<String> expected = Arrays.asList(expectedNames);
// when
Collections.sort(actual);
// then
assertTrue(actual.equals(expected));
}
}
The JUnit assertTrue here fails at runtime because the actual list is sorted into:
0 = "AACME"
1 = "ACME"
2 = "AGME"
3 = "AaCME"
4 = "Acme"
5 = "BCME"
6 = "CCME"
7 = "DCME"
8 = "aACME"
9 = "aCME"
Thats ^^^ debugger output, and the numbers represent the list index of each element.
So for some reason Collections.sort is saying that the string "BCME" is lexiconographically "lower" (will appear earlier in a sorted list) than "aCME", which is just plain nuts to me. :-)
I should mention that I will only be dealing with ASCII characters in UTF-8 here, but my application will perform pre-validation that assures us all characters in each string/name will be in the range of [a-z][A-Z].
Either way, the sorting rules I'm looking for my Java code to use are this:
- when I say "lower", I mean "will appear earlier in a sorted list" and when I say "higher" I mean "will appear later in a sorted list"
- hence I would say "3 is lower than 43", because in a sorted list of ints, 3 will appear earlier in that list than 43 would, etc.
- lower-case letters are lower than uppercase; so "a" should appear before "A"
- hence the order of all letters is
aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ
- hence the order of all letters is
- shorter words come before longer words, provided that they are an identical (casing included) subsets of the longer word
- "but" is lower than (comes before) "butterfly"
- "butterfly" is lower than "But" (b < B)
- "butterfly" is lower than "bUt" (b and b are the same, but u < U)
Given these sorting rules, the list from my unit test should sort into:
Sort Order Reason why it comes after the last one in the list
================================================================
aACME
aCME 1st letter is 'a' but 2nd letter is 'C' and A < C
AaCME 1st letter is 'A' and a < A
AACME 1st letter is 'A' and 2nd letter is 'A' and a < A
Acme 1st letter is 'A' but 2nd letter is 'c' and A < c
ACME 1st letter is 'A' but 2nd letter is 'C' and c < C
AGME 1st letter is 'A' but 2nd letter is 'G' and C < G
BCME 1st letter is 'B' and aA < bB
CCME 1st letter is 'C' and bB < cC
DCME 1st letter is 'D' and cC < dD
How can I change the code above so that the unit test passes and the list is sorted the way I need?