J'ai une liste de couleurs comme celle-ci:
Rose, bleu, rouge, bleu, gris, vert, violet, noir ... etc
List<String> listOfColors = Arrays.asList("Pink", "Blue", "Red", "blue", "Grey", "green", "purple", "black");
Il y a des opérations intermédiaires comme le filtrage de certaines couleurs de fruits, maintenant je reste avec des résultats filtrés où je veux qu'ils soient triés dans l'ordre:
Bleu, noir, bleu, gris, vert, rose, violet, rouge
J'ai essayé :
List<String> collect = listOfColors.stream().sorted(String::compareToIgnoreCase)
.collect(Collectors.toList());
Cela ne fonctionne pas comme prévu.
La sortie est la suivante:
noir, bleu, bleu, vert, gris, rose, violet, rouge
Je veux ce qui suit:
Bleu, noir, bleu, gris, vert, rose, violet, rouge
java
sorting
java-8
java-stream
Vishwa Ratna
la source
la source
a
est avantu
donc le résultat est correct[black, Blue, blue, green, Grey, Pink, purple, Red]
@ chrylis-onstrike-Réponses:
Ma solution est d'utiliser le tri en deux étapes en utilisant la
Comparator.thenComparing()
méthode.Tout d'abord, comparez les chaînes uniquement par le premier caractère en ignorant la casse. Les groupes avec le même premier caractère (quel que soit le cas) restent donc non triés jusqu'à présent. Ensuite, dans la deuxième étape, appliquez le tri alphabétique normal pour trier ces sous-groupes non triés.
Peut-être qu'il peut encore être optimisé, mais il donne le résultat souhaité:
la source
Comparator
. Mais oui, cela suppose de ne comparer que le premier caractère de la chaîne sur lequel l'OP n'a pas beaucoup insisté non plus.Vous pouvez utiliser RuleBasedCollator pour définir vos propres règles.
Exemple de règle personnalisée :
Production:
Modifier: Au lieu d'écrire à la
customRules
main, vous pouvez utiliser le code ci-dessous pour le générer.la source
String customRules
peut être de l'automatisme avecIntStream
:IntStream.range('a', 'z' + 1) .mapToObj(Character::toString) .flatMap(ch -> Stream.of("<", ch.toUpperCase(), "<", ch)) .collect(Collectors.joining(""))
.mapToObj(Character::toString)
ne sera pas résolu, je suppose que vous devez utiliser.mapToObj(c -> Character.toString((char) c))
mapToObj(Character::toString)
ne fonctionne que dans Java 11 ou plus récent.mapToObj(Character::toString)
je n'étais pas résolu, mais j'ai aimé l'idée, donc je finis par faire du casting comme.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("<", "<", ""));
Vous avez besoin d'une méthode qui effectue d'abord une comparaison insensible à la casse sur chaque lettre, puis s'il y a une correspondance, effectuez une comparaison sensible à la casse sur chaque lettre:
Vous pouvez ensuite transmettre cette méthode à
Stream.sorted
.la source