2010-03-19 18 views
48

Ho un generico Collection e sto cercando di capire come posso ordinare gli oggetti contenuti al suo interno. Ho provato alcune cose ma non riesco a far funzionare nessuno di loro.Come ordinare una collezione <T>?

risposta

65

Collezioni di per sé non hanno un ordine predefinito, pertanto è necessario convertirli in un java.util.List. Quindi è possibile utilizzare una forma di java.util.Collections.sort

Collection<T> collection = ...; 

List<T> list = new ArrayList<T>(collection); 

Collections.sort(list); 
// or 
Collections.sort(list, new Comparator<T>(){...}); 

// list now is sorted 
+3

Anche se questo risolve il problema, questo non lo sarà il modo più veloce per farlo, a meno che la raccolta stessa sia già una lista. – Fortega

+3

@Fortega: Allora mi illumini qual è il modo più veloce per ordinare una raccolta generale pur conservando tutti i suoi elementi. A proposito, questo è esattamente il metodo utilizzato da Google Collections 'Ordering.sortedCopy'. –

+0

Dipende dal tipo di raccolta. Per gli insiemi di cui il metodo toArray() (chiamato nel costruttore di ArrayList) ha bisogno di iterazione su tutti gli elementi (ad esempio: un Set), l'ordinamento potrebbe richiedere un ciclo aggiuntivo su tutti gli elementi. Puoi utilizzare le raccolte google TreeMultiset, che consente duplicati. Anche se le differenze probabilmente non saranno molto grandi e nello stesso ordine di grandezza. – Fortega

1

Ecco un esempio. (Sto usando CompareToBuilder classe da Apache per comodità, anche se questo può essere fatto senza utilizzarlo.)

import java.util.ArrayList; 
import java.util.Calendar; 
import java.util.Collections; 
import java.util.Comparator; 
import java.util.Date; 
import java.util.HashMap; 
import java.util.List; 
import org.apache.commons.lang.builder.CompareToBuilder; 

public class Tester { 
    boolean ascending = true; 

    public static void main(String args[]) { 
     Tester tester = new Tester(); 
     tester.printValues(); 
    } 

    public void printValues() { 
     List<HashMap<String, Object>> list = 
      new ArrayList<HashMap<String, Object>>(); 
     HashMap<String, Object> map = 
      new HashMap<String, Object>(); 

     map.put("actionId", new Integer(1234)); 
     map.put("eventId", new Integer(21) ); 
     map.put("fromDate", getDate(1)  ); 
     map.put("toDate", getDate(7)  ); 
     list.add(map); 

     map = new HashMap<String, Object>(); 
     map.put("actionId", new Integer(456)); 
     map.put("eventId", new Integer(11) ); 
     map.put("fromDate", getDate(1)  ); 
     map.put("toDate", getDate(1)  ); 
     list.add(map); 

     map = new HashMap<String, Object>(); 
     map.put("actionId", new Integer(1234)); 
     map.put("eventId", new Integer(20) ); 
     map.put("fromDate", getDate(4)  ); 
     map.put("toDate", getDate(16)  ); 
     list.add(map); 

     map = new HashMap<String, Object>(); 
     map.put("actionId", new Integer(1234)); 
     map.put("eventId", new Integer(22) ); 
     map.put("fromDate", getDate(8)  ); 
     map.put("toDate", getDate(11)  ); 
     list.add(map); 


     map = new HashMap<String, Object>(); 
     map.put("actionId", new Integer(1234)); 
     map.put("eventId", new Integer(11) ); 
     map.put("fromDate", getDate(1)  ); 
     map.put("toDate", getDate(10)  ); 
     list.add(map); 

     map = new HashMap<String, Object>(); 
     map.put("actionId", new Integer(1234)); 
     map.put("eventId", new Integer(11) ); 
     map.put("fromDate", getDate(4)  ); 
     map.put("toDate", getDate(15)  ); 
     list.add(map); 

     map = new HashMap<String, Object>(); 
     map.put("actionId", new Integer(567)); 
     map.put("eventId", new Integer(12) ); 
     map.put("fromDate", getDate(-1)  ); 
     map.put("toDate", getDate(1)  ); 
     list.add(map); 

     System.out.println("\n Before Sorting \n "); 
     for(int j = 0; j < list.size(); j++) 
      System.out.println(list.get(j)); 

     Collections.sort(list, new HashMapComparator2()); 

     System.out.println("\n After Sorting \n "); 
     for(int j = 0; j < list.size(); j++) 
      System.out.println(list.get(j)); 
    } 

    public static Date getDate(int days) { 
     Calendar cal = Calendar.getInstance(); 
     cal.setTime(new Date()); 
     cal.add(Calendar.DATE, days); 
     return cal.getTime(); 
    } 

    public class HashMapComparator2 implements Comparator { 
     public int compare(Object object1, Object object2) { 
      if(ascending) { 
       return new CompareToBuilder() 
        .append(
         ((HashMap)object1).get("actionId"), 
         ((HashMap)object2).get("actionId") 
        ) 
        .append(
         ((HashMap)object2).get("eventId"), 
         ((HashMap)object1).get("eventId") 
        ) 
       .toComparison(); 
      } else { 
       return new CompareToBuilder() 
        .append(
         ((HashMap)object2).get("actionId"), 
         ((HashMap)object1).get("actionId") 
        ) 
        .append(
         ((HashMap)object2).get("eventId"), 
         ((HashMap)object1).get("eventId") 
        ) 
       .toComparison(); 
      } 
     } 
    } 
} 

Se si dispone di un codice specifico che si sta lavorando e stanno avendo problemi, è possibile pubblicare il tuo codice di pseudo e possiamo provare ad aiutarti!

+0

Thx per la risposta, ma ho una collezione generica questo esempio non funziona per me – Mercer

4

Non si può se T è tutto ciò che si ottiene. Bisogna avere l'esso iniettata dal provider attraverso:

Collection<T extends Comparable> 

o passare in Confronto tramite il metodo Collections.sort (...)

9

Un Collection non ha un ordinamento, così volendo ordinarlo non ha senso. È possibile ordinare List istanze e gli array, ei metodi per farlo sono Collections.sort() e Arrays.sort()

6

Se l'oggetto delle raccolte è un elenco, utilizzerei il metodo di ordinamento, come proposto nelle altre risposte.

Tuttavia, se non è una lista, e non mi importa di quello che tipo di oggetto Collection viene restituito, penso che sia più veloce di creare un TreeSet invece di una lista:

TreeSet sortedSet = new TreeSet(myComparator); 
sortedSet.addAll(myCollectionToBeSorted); 
+0

TreeSet richiede che Comparable sia implementato, se si desidera che il set sia ordinato. Questo è quello che faccio di solito quando ho bisogno di una collezione ordinata. TreeSet eliminerà anche i duplicati. – David

+1

TreeSet non richiede Paragonabile per essere implementato se si utilizza un comparatore. Tuttavia, hai ragione sui duplicati. – Fortega

+0

OOPS- mancato il comparatore seduto lì. Implemento sempre Comparable, quindi mi sono perso completamente. – David

1

Supponendo di aver un elenco di oggetti di tipo persona, usando l'espressione lambda, è possibile ordinare gli ultimi nomi degli utenti, per esempio nel modo seguente:

import java.util.Arrays; 
import java.util.Collections; 
import java.util.Comparator; 
import java.util.List; 

class Person { 
     private String firstName; 
     private String lastName; 

     public Person(String firstName, String lastName){ 
      this.firstName = firstName; 
      this.lastName = lastName; 
     } 

     public String getLastName(){ 
      return this.lastName; 
     } 

     public String getFirstName(){ 
      return this.firstName; 
     } 

     @Override 
     public String toString(){ 
      return "Person: "+ this.getFirstName() + " " + this.getLastName(); 
     } 
    } 

    class TestSort { 
     public static void main(String[] args){ 
      List<Person> people = Arrays.asList(
            new Person("John", "Max"), 
            new Person("Coolio", "Doe"), 
            new Person("Judith", "Dan") 
      ); 

      //Making use of lambda expression to sort the collection 
      people.sort((p1, p2)->p1.getLastName().compareTo(p2.getLastName())); 

      //Print sorted 
      printPeople(people); 
     } 

     public static void printPeople(List<Person> people){ 
      for(Person p : people){ 
       System.out.println(p); 
      } 
     } 
    } 
Problemi correlati