Jon Jon - 1 year ago 66
Java Question

Sorting Strings that contain integers with comparator

I have a comparator that sorts an array of strings that contain letters and numbers, but can't seem to identify the regular expression that sorts them in the manner I am looking for.

I have used this question as a reference for my comparator.

array={string-a01,string-a20,string-a100,string-b01,string-b20,string-b100,string-c01,string-c20,string-c100 etc.}

Collections.sort(array, 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 num.isEmpty() ? 0 : Integer.parseInt(num);

for (String element : array) {

Before Introducing the comparator the output was:

string-a01, string-a100, string-a20, string-b01, string-b100, string-b20, string-c01, string-c20, string-c100

The output that this code produces is:

string-a01, string-b01, string-c01 string-a20, string-b20, string-c20 string-a100, string-b100, string-c100

The output I would like it to produce is:

string-a01, string-a20, string-a100, string-b01, string-b20, string-b100, string-c01, string-c20, string-c100

EDIT: Edited for clarification. Array has been changed and output before the comparator was added.

Answer Source

Assuming that the string part is actually something else than just "string". You can extract the letter part of the ending, and the digit part, and compare those using a composite Comparator:

String[] array = { "string-a20", "string-a01", "string-b01",
    "string-b20", "string-c01", "string-c20",
    "string-a100", "string-b100", "string-c100" };

Pattern p = Pattern.compile("^.*?-([A-Za-z]+)(\\d+)$");

List<String> result =
    .sorted(Comparator.comparing((Matcher m) -> // Compare the letter part
        .thenComparingInt(m -> Integer.parseInt( // Compare the number part
    .map(m -> // Map back to String



[string-a01, string-a20, string-a100, string-b01, string-b20, string-b100, string-c01, string-c20, string-c100]

Legacy version (With the downside of having to recreate Matchers):

Arrays.sort(array, new Comparator<String>() {

    public int compare(String o1, String o2) {
        Matcher m1 = p.matcher(o1);
        Matcher m2 = p.matcher(o2);

        if(!(m1.find() && m2.find()))
            return 0; // Or throw a format exception

        int comparison =;
        return comparison != 0
            ? comparison 
            :, Integer.parseInt(;