web-dev-qa-db-fra.com

Trier alphabétiquement une collection Java basée sur la valeur 'toString' de ses éléments membres

Supposons que j'ai défini un utilisateur Java classe appelée Foo telle que:

public class Foo 
{

    private String aField;

    @Override
    public String toString()
    {
        return aField;
    }

}

Et une collection comme:

List<Foo> aList;

Ce que je cherche à faire est de trier la liste par ordre alphabétique en fonction de la valeur ".toString ()" renvoyée par chaque membre.

J'ai essayé d'utiliser la méthode Collections.sort (), mais le résultat n'était pas ce que j'essayais. Que dois-je faire pour y parvenir?

25
Tom Neyland

Utilisez l'API sort(List list, Comparator c) qui spécifie un comparateur et implémentez comme vous le souhaitez.

Alternativement, si vous n'avez pas spécifiquement besoin d'une liste, utilisez un SortedSet , il en va de même avec le comparateur.

18
Yuval Adam
Collections.sort(fooList,
                 new Comparator<Foo>()
                 {
                     public int compare(Foo f1, Foo f2)
                     {
                         return f1.toString().compareTo(f2.toString());
                     }        
                 });

En supposant que toString ne retourne jamais null et qu'il n'y a aucun élément null dans la liste.

67
Dan Dyer

google-collections rend cela très facile avec Commande :

Collections.sort(list, Ordering.usingToString());

Est-il utile de faire appel à une bibliothèque tierce uniquement pour utiliser quelque chose que vous pourriez écrire trivialement en utilisant un comparateur (comme d'autres l'ont fourni)? Non, mais google-collections est tellement cool que vous voudrez l'avoir quand même pour un tas d'autres raisons.

Sur le front du tri, vous pouvez également facilement faire des choses comme inverser:

Ordering.usingToString().reverse();

ou rompre les liens:

Ordering.usingToString().compound(someOtherComparator);

ou gérer les nulls:

Ordering.usingToString().nullsFirst();

etc., mais il y a beaucoup plus de choses là-dedans (pas seulement liées au tri, bien sûr) qui conduisent à un code vraiment expressif. Vérifiez-le!

16
Cowan
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.sort (liste);

7
Pierre

La version Java 8:

list.sort(Comparator.comparing(Object::toString));

Ou en streaming:

List<Foo> sortedList = unsortedList
    .stream()
    .sorted(Comparator.comparing(Object::toString)))
    .collect(Collectors.toList());
5
David Leppik

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 le suggère Pierre.

5
psykotedy

lambdaj vous permet de trier, filtrer et en général manipuler les collections sans écrire de boucles ni obscurcir les classes internes. Par exemple, le tri que vous demandiez peut être réalisé comme suit:

sort(foos, on(Foo.class).toString());

Si vous êtes intéressé, consultez-le sur:

http://code.google.com/p/lambdaj/

3
Mario Fusco

Je vous conseille fortement de n'utiliser toString qu'à des fins de débogage ... cependant ... pour développer ce que Yuval A a écrit ci-dessus ...

 public class X 
 implémente 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 Compartor approprié qui n'utilise pas toString.

3
TofuBeer

Si vous souhaitez 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 la méthode Collections.sort déjà mentionnée par Yuval.

1
Paul Tomblin