Trier par ordre alphabétique une Collection Java en fonction de la valeur' toString ' de ses éléments membres
Supposons que J'ai une classe Java définie par L'utilisateur appelée Foo telle que:
public class Foo
{
private String aField;
@Override
public String toString()
{
return aField;
}
}
Et une Collection telle que:
List<Foo> aList;
Ce que je cherche à faire est de trier la liste Par Ordre alphabétique en fonction de chaque membre retourné '.ToString () ' valeur.
J'ai essayé d'utiliser les Collections.méthode sort (), mais le résultat n'était pas ce que j'essayais. Que dois-je faire pour accomplir cela?
9 réponses
Utilisez L'API sort(List list, Comparator c)
qui spécifie un comparateur, et implémentez est comme vous le souhaitez.
Sinon, si vous n'avez pas spécifiquement besoin D'une liste, utilisez un SortedSet
, il en va de même avec le comparateur.
Collections.sort(fooList,
new Comparator<Foo>()
{
public int compare(Foo f1, Foo f2)
{
return f1.toString().compareTo(f2.toString());
}
});
En supposant que toString ne renvoie jamais null et qu'il n'y a pas d'éléments null dans la liste.
Google-collections fait vraiment facilement avec la Commande:
Collections.sort(list, Ordering.usingToString());
Est-ce que l'introduction d'une bibliothèque 3rd entière juste pour utiliser quelque chose que vous pourriez écrire trivialement en utilisant un comparateur (comme d'autres l'ont fourni) en vaut la peine? Non, mais Google-collections est tellement cool que vous voudrez l'avoir de toute façon pour un tas d'autres raisons.
Sur le front de tri, vous pouvez également facilement faire des choses comme inverser:
Ordering.usingToString().reverse();
Ou briser les liens:
Ordering.usingToString().compound(someOtherComparator);
Ou traiter avec les valeurs null:
Ordering.usingToString().nullsFirst();
Etc., mais il y a beaucoup plus de choses là-dedans (pas seulement liées au tri, bien sûr) qui conduit à un code vraiment expressif. Check it out!
public class Foo
implements Comparable<Foo>
{
private String aField;
public Foo(String s)
{
aField=s;
}
public String getAField()
{
return aField;
}
public int compareTo(Foo other)
{
return getAField().compareTo(other.getAField());
}
@Override
public String toString()
{
return getAField();
}
}
, puis
Collections.trier (liste);
Je ferais quelque chose de très similaire à Pierre:
public class Foo implements Comparable<Foo>
{
private String aField;
@Override
public String toString()
{
return aField;
}
public int compareTo(Foo o)
{
return this.toString().compareTo(o.toString());
}
}
Ensuite, comme Pierre, j'utiliserais Collections.sort(list)
Comme Pierre le suggère.
Je vous conseille fortement d'utiliser uniquement toString à des fins de débogage... cependant... pour développer ce que Yuval a écrit ci-dessus...
public class X implements Comparator { public int compare(final Foo a, final Foo b) { return (a.toString().compareTo(b.toString())); } }
Cependant, vous devriez vraiment avoir Foo implémenter Comarable ou écrire un Comparteur approprié qui n'utilise pas toString.
Lambdaj vous permet de trier, filtrer et en général manipuler des collections sans écrire de boucles ou de classes internes obscures. Par exemple, le tri que vous demandiez peut être réalisé comme suit:
sort(foos, on(Foo.class).toString());
Si cela vous intéresse, consultez-le à:
La version Java 8:
list.sort(Comparator.comparing(Object::toString));
Ou streaming:
List<Foo> sortedList = unsortedList
.stream()
.sorted(Comparator.comparing(Object::toString)))
.collect(Collectors.toList());
Si vous voulez que la collection reste triée, plutôt que de la Trier à des points spécifiques, vous pouvez la placer dans un TreeSet avec un comparateur défini. Sinon, j'utiliserais les Collections.méthode de tri déjà mentionnée par Yuval.