J'ai un tableau d'objets person (int age; String name;)
.
Comment puis-je trier ce tableau par ordre alphabétique par nom, puis par âge?
Quel algorithme utiliseriez-vous pour cela?
Vous pouvez utiliser Collections.sort
comme suit:
private static void order(List<Person> persons) {
Collections.sort(persons, new Comparator() {
public int compare(Object o1, Object o2) {
String x1 = ((Person) o1).getName();
String x2 = ((Person) o2).getName();
int sComp = x1.compareTo(x2);
if (sComp != 0) {
return sComp;
}
Integer x1 = ((Person) o1).getAge();
Integer x2 = ((Person) o2).getAge();
return x1.compareTo(x2);
}});
}
List<Persons>
est maintenant trié par nom, puis par âge.
String.compareTo
"Compare deux chaînes lexicographiquement" - à partir de la documentation .
Collections.sort
est une méthode statique dans la bibliothèque native Collections. Il fait le tri proprement dit, il vous suffit de fournir un comparateur qui définit comment deux éléments de votre liste doivent être comparés: ceci est réalisé en fournissant votre propre implémentation de la compare
méthode.
Comparator
pour éviter d'avoir à convertir les entrées.Comparable
. Voir la réponse de @ berry120Comparator<Person> comparator = Comparator.comparing(Person::getName).thenComparingInt(Person::getAge);
Pour ceux qui sont capables d'utiliser l'API de streaming Java 8, il existe une approche plus soignée qui est bien documentée ici: Lambdas et tri
Je cherchais l'équivalent du C # LINQ:
J'ai trouvé le mécanisme en Java 8 sur le comparateur:
Voici donc l'extrait de code qui illustre l'algorithme.
Consultez le lien ci-dessus pour une manière plus soignée et une explication sur la façon dont l'inférence de type de Java la rend un peu plus difficile à définir par rapport à LINQ.
Voici le test unitaire complet pour référence:
la source
Comparator<Person> comparator = Comparator.comparing(Person::getName).thenComparing(Person::getAge);
thenComparingInt
pour l'âge (int)Collections.sort(people, comparator);
place?Utilisation de l'approche Java 8 Streams ...
Et l'approche Java 8 Lambda ...
Enfin...
la source
Vous devez implémenter le vôtre
Comparator
, puis l'utiliser: par exempleVotre comparateur pourrait ressembler un peu à ceci:
Le comparateur compare d'abord les noms, s'ils ne sont pas égaux, il renvoie le résultat de leur comparaison, sinon il renvoie le résultat de la comparaison lors de la comparaison des âges des deux personnes.
Ce code n'est qu'un brouillon: comme la classe est immuable, vous pourriez penser à en créer un singleton, en créant plutôt une nouvelle instance pour chaque tri.
la source
Vous pouvez utiliser l'approche Java 8 Lambda pour y parvenir. Comme ça:
la source
Demandez à votre classe de personne d'implémenter
Comparable<Person>
, puis d'implémenter la méthode compareTo, par exemple:Cela triera d'abord par nom (insensible à la casse), puis par âge. Vous pouvez ensuite exécuter
Arrays.sort()
ouCollections.sort()
sur la collection ou le tableau d'objets Person.la source
Guava's
ComparisonChain
fournit une manière propre de le faire. Reportez-vous à ce lien .Un utilitaire pour exécuter une instruction de comparaison chaînée. Par exemple:
la source
Vous pouvez faire comme ceci:
la source
Utilisez
Comparator
puis mettez des objets dansCollection
, puisCollections.sort();
la source
Créez autant de comparateurs que nécessaire. Ensuite, appelez la méthode "thenComparing" pour chaque catégorie de commande. C'est une façon de faire par Streams. Voir:
Look: Trier l'objet défini par l'utilisateur sur plusieurs champs - Comparateur (flux lambda)
la source
Je ferais attention lors de l'utilisation de Guava
ComparisonChain
car cela crée une instance de celui-ci par élément comparé afin que vous regardiez une création deN x Log N
chaînes de comparaison juste pour comparer si vous triez, ouN
instances si vous itérez et vérifiez l'égalité.Je créerais plutôt un statique en
Comparator
utilisant la dernière API Java 8 si possible ou l'Ordering
API Guava qui vous permet de le faire, voici un exemple avec Java 8:Voici comment utiliser l'
Ordering
API de Guava : https://github.com/google/guava/wiki/OrderingExplainedla source
compare
méthode ne crée rien, mais renvoie l'une des instances singletonLESS
,GREATER
ouACTIVE
selon le résultat de la comparaison. Il s'agit d'une approche hautement optimisée et n'ajoute aucune surcharge de mémoire ou de performances.Ou vous pouvez exploiter le fait que
Collections.sort()
(ouArrays.sort()
) est stable (il ne réorganise pas les éléments égaux) et utiliser unComparator
pour trier d'abord par âge, puis un autre pour trier par nom.Dans ce cas précis, ce n'est pas une très bonne idée, mais si vous devez être en mesure de modifier l'ordre de tri au moment de l'exécution, cela peut être utile.
la source
Vous pouvez utiliser le comparateur en série générique pour trier les collections selon plusieurs champs.
la source
Version mise à jour:
la source
Pour une classe
Book
comme celle-ci:tri de la classe principale avec des objets simulés
la source
Je ne suis pas sûr que ce soit moche d'écrire le compartiment dans la classe Person dans ce cas. A fait ça comme ça:
la source