2009-02-16 9 views
20

Si supponga che ho una classe Java definita dall'utente chiamato Foo come ad esempio:alfabetico Ordina una collezione Java basato sul valore 'toString' dei suoi prodotti Membro

public class Foo 
{ 

    private String aField; 

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

} 

e una collezione come ad esempio:

List<Foo> aList; 

Quello che sto cercando di fare è ordinare la lista in ordine alfabetico in base al valore restituito da '.toString()' di ogni membro.

Ho provato a utilizzare il metodo Collections.sort(), ma il risultato non era quello che stavo tentando. Cosa devo fare per eseguire questo inorder?

risposta

17

Utilizzare l'API sort(List list, Comparator c) che specifica un comparatore e implementare come desiderato.

In alternativa, se non si ha specificamente bisogno di un elenco, utilizzare uno SortedSet, lo stesso vale per il comparatore.

1

Se si desidera che la raccolta rimanga ordinata, anziché ordinarla in punti specifici, è possibile inserirla in un set di alberi con un comparatore definito. Altrimenti, userei il metodo Collections.sort già menzionato da Yuval.

+0

già modificato il mio messaggio a parlare SortedSet;) –

6
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(); 
    } 

} 

e poi

Collections.sort (lista);

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

Supponendo che toString non restituisca mai null e che non ci siano elementi nulli nell'elenco.

+0

In particolare digitando questo comparatore può essere inutile, in quanto il richiedente vuole semplicemente per confrontare due oggetti di toString. Mi sembra che il tipo potrebbe non essere necessario. –

+0

@Nathan. Sì, il tipo generico non ha bisogno di essere più specifico di Object. Non è necessario definire il comparatore in linea come ho fatto io. –

+0

Che è ancora più bello in Java 8 con un lambda. –

3

vi consiglio caldamente di utilizzare solo toString a scopo di debug ... però ... per espandere su ciò che Yuval A ha scritto sopra ...

 
public class X 
    implements Comparator 
{ 
    public int compare(final Foo a, final Foo b) 
    { 
     return (a.toString().compareTo(b.toString())); 
    } 
} 

Tuttavia si dovrebbe davvero avere Foo implementare Comarable o scrivi un Compartor appropriato che non faccia uso di toString.

5

vorrei fare qualcosa di molto simile a 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()); 
    } 
} 

Poi, come Pierre, userei Collections.sort(list) come suggerisce Pierre.

2

lambdaj consente di ordinare, filtrare e in generale manipolare le raccolte senza loop di scrittura o classi interne oscure. Per esempio l'ordinamento che stavi chiedendo può essere raggiunto come segue:

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

Se siete interessati a questo controllo fuori a:

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

+0

Fantastico, non avevo mai sentito parlare di lambdaj, ma posso vedere immediatamente quanto possa essere utile. –

+0

Hey volevo solo farti sapere che sto usando lambdaj in un nuovo progetto e funziona bene. Grazie ancora. –

+0

Se sei un utente di lambdaj felice, potresti essere fantastico se aggiungerai le tue impressioni qui. Grazie :) http://code.google.com/p/lambdaj/wiki/WhoIsUsingLambdaj –

14

google-collections rende il tutto veramente facile con Ordering:

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

Introdurre un'intera libreria di terze parti solo per utilizzare qualcosa che potresti scrivere banalmente utilizzando un tor (come altri hanno fornito) utile? No, ma le raccolte di google sono così belle che vorrai averlo comunque per un sacco di altri motivi.

Sul fronte di ordinamento, si può anche facilmente fare cose come la retromarcia:

Ordering.usingToString().reverse(); 

o rompere i legami:

Ordering.usingToString().compound(someOtherComparator); 

o affrontare nulli:

Ordering.usingToString().nullsFirst(); 

etc. , ma ci sono un sacco di cose in più (non solo per l'ordinamento, ovviamente) che portano a un codice veramente espressivo. Controlla!

2

La versione Java 8:

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

Streaming:

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