I have problem with default comparator for Strings (in SortedSet). The problem is that default comparator doesn't sort good String that contains numbers i.e.: In set i have:
room1, room2, room100
Natural ordering should be like above but in set I have:
room1, room100, room2
I know why it is but I don't know how to change it.
Sort String in Java There is no direct method to sort a string in Java. You can use Arrays, which has a method CharArray() that will create a char input string and using another method (Arrays.
The string class doesn't have any method that directly sorts a string, but we can sort a string by applying other methods one after another. The string is a sequence of characters. In java, objects of String are immutable which means a constant and cannot be changed once created.
Try this comparator, which removes all non-digit characters then compares the remaining characters as numbers:
Collections.sort(strings, new Comparator<String>() { public int compare(String o1, String o2) { return extractInt(o1) - extractInt(o2); } int extractInt(String s) { String num = s.replaceAll("\\D", ""); // return 0 if no digits found return num.isEmpty() ? 0 : Integer.parseInt(num); } });
Here's a test:
public static void main(String[] args) throws IOException { List<String> strings = Arrays.asList("room1.2", "foo1.1", "foo", "room2.3", "room100.999", "room10", "room.3"); Collections.sort(strings, new Comparator<String>() { public int compare(String o1, String o2) { return extractInt(o1) - extractInt(o2); } int extractInt(String s) { String num = s.replaceAll("\\D", ""); // return 0 if no digits found return num.isEmpty() ? 0 : Integer.parseInt(num); } }); System.out.println(strings); }
Output:
[foo, room1, room2, room10, room100]
When the numbers are decimals (also demonstrating Java 8+ style):
public static void main(String[] args) { List<String> strings = Arrays.asList("room1.2", "foo1.1", "room2.3", "room100.999", "room10", "room.3"); Collections.sort(strings, Comparator.comparing(Application::extractDouble)); System.out.println(strings); } static double extractDouble(String s) { String num = s.replaceAll("[^\\d.]", ""); // return 0 if no digits found return num.isEmpty() ? 0 : Double.parseDouble(num); }
Result:
[foo, room.3, foo1.1, room1.2, room2.3, room10, room100.999]
Used @bohemian answer. Just improved a bit. This worked for me very well..
Collections.sort(asdf, new Comparator<String>() { public int compare(String o1, String o2) { String o1StringPart = o1.replaceAll("\\d", ""); String o2StringPart = o2.replaceAll("\\d", ""); if(o1StringPart.equalsIgnoreCase(o2StringPart)) { return extractInt(o1) - extractInt(o2); } return o1.compareTo(o2); } int extractInt(String s) { String num = s.replaceAll("\\D", ""); // return 0 if no digits found return num.isEmpty() ? 0 : Integer.parseInt(num); } });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With