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);
            }
        });