Sorting Strings that contains number in Java [duplicate]
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.
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);
}
});