Tengo una lista de colores como esta:
Rosa, azul, rojo, azul, gris, verde, morado, negro ... etc.
List<String> listOfColors = Arrays.asList("Pink", "Blue", "Red", "blue", "Grey", "green", "purple", "black");
Hay algunas operaciones intermedias como filtrar algunos colores de frutas, ahora me quedo con los resultados filtrados donde quiero que se ordenen en orden:
Azul, negro, azul, gris, verde, rosa, morado, rojo
Yo he tratado :
List<String> collect = listOfColors.stream().sorted(String::compareToIgnoreCase)
.collect(Collectors.toList());
No funciona como se esperaba.
El resultado es el siguiente:
negro, azul, azul, verde, gris, rosa, morado, rojo
Quiero lo siguiente:
Azul, negro, azul, gris, verde, rosa, morado, rojo
java
sorting
java-8
java-stream
Vishwa Ratna
fuente
fuente
a
es antes,u
así que el resultado es correcto[black, Blue, blue, green, Grey, Pink, purple, Red]
@ chrylis-onstrike-Respuestas:
Mi solución es usar la clasificación en dos pasos usando el
Comparator.thenComparing()
métodoPrimero, compare las cadenas solo por el primer carácter ignorando mayúsculas y minúsculas. Por lo tanto, los grupos con el mismo primer carácter (sin importar el caso) permanecen sin clasificar hasta ahora. Luego, en el segundo paso, aplique la ordenación alfabética normal para ordenar los subgrupos sin clasificar.
Quizás todavía se puede optimizar, pero da el resultado deseado:
fuente
Comparator
. Pero sí, esto supone solo comparar el primer carácter de la Cadena sobre el cual el OP tampoco ha enfatizado demasiado.Puede usar RuleBasedCollator para definir sus propias Reglas.
Ejemplo de regla personalizada :
Salida:
Editar: en lugar de escribirlo a
customRules
mano, puede usar el siguiente código para generarlo.fuente
String customRules
puede ser automatismo conIntStream
:IntStream.range('a', 'z' + 1) .mapToObj(Character::toString) .flatMap(ch -> Stream.of("<", ch.toUpperCase(), "<", ch)) .collect(Collectors.joining(""))
.mapToObj(Character::toString)
no se resolverá, supongo que debes usar.mapToObj(c -> Character.toString((char) c))
mapToObj(Character::toString)
solo funciona en Java 11 o más reciente.mapToObj(Character::toString)
no me estaba resolviendo, pero me gustó la idea, así que termino haciendo casting como.mapToObj(c -> Character.toString((char) c))
IntStream.rangeClosed('a', 'z').flatMap(c -> IntStream.of(c,Character.toUpperCase(c))) .mapToObj(c -> Character.toString((char)c)) .collect(Collectors.joining("<", "<", ""));
Necesita un método que primero haga una comparación entre mayúsculas y minúsculas en cada letra, luego, si hay una coincidencia, realice una comparación entre mayúsculas y minúsculas en cada letra:
Luego puede pasar este método a
Stream.sorted
.fuente