Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting Strings that contains number in Java [duplicate]

Tags:

java

sorting

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.

like image 224
MAGx2 Avatar asked Dec 20 '12 13:12

MAGx2


People also ask

How does Java sort strings of numbers?

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.

Is it possible to sort a string in Java?

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.


2 Answers

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] 
like image 149
Bohemian Avatar answered Oct 01 '22 19:10

Bohemian


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);             }         }); 
like image 34
vamsi Avatar answered Oct 01 '22 20:10

vamsi