Clasificación de cadenas que contiene un número en Java

Tengo un problema con el comparador predeterminado para cadenas (en SortedSet). El problema es que el comparador predeterminado no ordena una buena Cadena que contenga números, es decir: En el conjunto tengo:

room1, room2, room100 

El orden natural debería ser como el de arriba, pero en el conjunto tengo:

 room1, room100, room2 

Sé por qué lo es, pero no sé cómo cambiarlo.

Pruebe este comparador, que elimina todos los caracteres que no sean dígitos y luego compara los caracteres restantes como números:

 Collections.sort(strings, new Comparator() { 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); } }); 

Aquí hay una prueba:

 public static void main(String[] args) throws IOException { List strings = Arrays.asList("room1", "foo", "room2", "room100", "room10"); Collections.sort(strings, new Comparator() { 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); } 

Salida:

 [foo, room1, room2, room10, room100] 

prueba esto. Supuse que siempre tendrás “habitación” al comienzo de tu cadena.

  List list = Arrays.asList("room1", "room100", "room2"); Collections.sort(list, new Comparator() { @Override public int compare(String o1, String o2) { return new Integer(o1.replaceAll("room", "")) .compareTo(new Integer(o2.replaceAll("room", ""))); } }); 

Utiliza @bohemian respuesta. Solo mejoré un poco. Esto funcionó muy bien para mí …

  Collections.sort(asdf, new Comparator() { 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); } }); 

Esta es la implementación de mi Comparator para dicho tipo: (las cadenas pueden comenzar desde cualquier carácter)

 public class StringNumberComparator implements Comparator{ @Override public int compare(String o1, String o2) { int i1 = this.getRearInt(o1); int i2 = getLeadingInt(o2); String s1 = getTrailingString(o1); String s2 = getTrailingString(o2); if(i1==i2) return s1.compareTo(s2); if(i1>i2) return 1; else if(i1 

Puede implementar un comparador y pasarlo al constructor del conjunto. Ver http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Comparator.html .

Si todas sus cadenas están en forma de sala [número], puede quitar la “sala” para analizar el número y compararlo.
Alternativamente, puede almacenar enteros en su configuración e imprimirlos con el prefijo de “sala”.

Una alternativa diferida sería hacer que el comparador String funcione sin hacer nada adicional (definiendo su propio comparador). Puedes tener eso rellenando con ceros los números dentro de tu String como este: room0001, room0002, room0100 entonces el comparador String predeterminado funcionará. Sin embargo, necesita saber el valor numérico máximo para que pueda adaptar su relleno en consecuencia.