You need to specify a custom Comparator<String>
to the Collections.sort()
method that defines the ordering that you want for the strings.
This works for a number at any position in the string, and also handles strings that have no numbers (falls back to ordinary string comparison with natural ordering):
final Pattern intsOnly = Pattern.compile("\\d+");
Comparator<String> comparator = new Comparator<String>() {
@Override
public int compare(final String string1, final String string2) {
String int1 = null;
String int2 = null;
Matcher matcher1 = intsOnly.matcher(string1);
if (matcher1.find()) {
int1 = matcher1.group();
Matcher matcher2 = intsOnly.matcher(string2);
if (matcher2.find()) {
int2 = matcher2.group();
}
}
if (int1 == null || int2 == null) { return string1.compareTo(string2); }
return Integer.valueOf(int1).compareTo(Integer.valueOf(int2));
}
};
Collections.sort(strings, comparator);
Of course this means that Truck1 will come before Car2, but that is how you wanted it according to your question.
UPDATE:
The above solution does not make sure that Car6 will come before Truck6. If you also want to fall back to natural string ordering in case of equal numbers, use this:
final Pattern intsOnly = Pattern.compile("\\d+");
Comparator<String> comparator = new Comparator<String>() {
@Override
public int compare(final String string1, final String string2) {
String int1 = null;
String int2 = null;
Matcher matcher1 = intsOnly.matcher(string1);
if (matcher1.find()) {
int1 = matcher1.group();
Matcher matcher2 = intsOnly.matcher(string2);
if (matcher2.find()) {
int2 = matcher2.group();
}
}
int result = 0;
if (int1 != null && int2 != null) {
result = Integer.valueOf(int1).compareTo(Integer.valueOf(int2));
}
if (result == 0) {
return string1.compareTo(string2);
}
else {
return result;
}
}
};
Collections.sort(strings, comparator);