venerdì 29 luglio 2011

Ordinare liste usando java.lang.Comparable e java.util.Comparator


Per ordinare liste di oggetti in Java sono a disposizione  due interfacce:

  • java.lang.Comparable
  • java.util.Comparator

L’interfaccia java.lang.comparable di solito si utilizza per definire l’ordinamento “naturale” di un oggetto e consta di un metodo con firma

 int compareTo(T o)

che paragona l’oggetto corrente (this) con l’oggetto fornito in input al metodo (o).
Il risultato sarà:
  • un intero positivo se this>o
  • 0 se sono uguali
  • un intero negativo se this<0

Vediamo un esempio



public class Persona implements Comparable<Persona> {
       public Persona(){
            
       }
       public Persona(String nome,String cognome,int eta){
             this.nome=nome;
             this.cognome=cognome;
             this.eta=eta;
       }
       private String nome;
       private String cognome;
       private int eta;
       public String getNome() {
             return nome;
       }
       public void setNome(String nome) {
             this.nome = nome;
       }
       public String getCognome() {
             return cognome;
       }
       public void setCognome(String cognome) {
             this.cognome = cognome;
       }
       public int getEta() {
             return eta;
       }
       public void setEta(int eta) {
             this.eta = eta;
       }
       @Override
       public int compareTo(Persona o) {
            
             return this.cognome.compareTo(o.cognome);
       }
       public String toString(){
             StringBuffer sb=new StringBuffer();
            
             sb.append(this.cognome);
             sb.append("  ");
             sb.append(this.nome);
             sb.append("  ");
             sb.append(this.eta);
            
             return sb.toString();
       }

}










































L’ordinamento definito è sul cognome; si noti che utilizziamo il metodo compareTo dell’oggetto String che di default ordina in modo alfabetico crescente (A-Z).

L’interfaccia java.util.Comparator si utilizza invece quando si vogliono definire ordinamenti alternativi dell’oggetto.
Si crea dunque una classe a parte che implementa l’interfaccia con il seguente metodo:

public int compare(T a,T b);

Il risultato sarà:
  • un intero positivo se a>b
  • 0 se sono uguali
  • un intero negativo se a<b

Vediamo un comparator che ordini le persone per età:

import java.util.Comparator;

public class PersonaEtaComparator implements Comparator<Persona> {

      @Override
      public int compare(Persona p1, Persona p2) {
            int retVal=0;
            if(p1.getEta()>p2.getEta())
            {
                  retVal=1;
            }
            else if(p1.getEta()<p2.getEta())
            {
                  retVal=-1;
            }
            return retVal;
      }

}


A questo punto vediamo il risultato eseguendo il seguente main; procederemo prima alla stampa dei record così come sono inseriti, poi ordinandoli per ordinamento naturale ed infine per età.




public class TestOrdinamento {

      /**
       * @param args
       */
      public static void main(String[] args) {
            LinkedList<Persona> lista=new LinkedList<Persona>();
            popolaPersona(lista);
            System.out.println("Non ordinata>>"+lista);
            Collections.sort(lista);
            System.out.println("Ordinamento Naturale>>"+lista);
            Collections.sort(lista,new PersonaEtaComparator());
            System.out.println("Ordinamento per età>>"+lista);

      }
      private static void popolaPersona(LinkedList<Persona> lista)
      {
            lista.add(new Persona("mario","rossi",25));
            lista.add(new Persona("luigi", "bianchi", 55));
            lista.add(new Persona("mario","verdi",14));
            lista.add(new Persona("luigi", "gialli", 45));
            lista.add(new Persona("mario","maffei",32));
            lista.add(new Persona("luigi", "servillo", 56));
      }

}



L’output prodotto dalle 3 liste sarà:


Non ordinata>>[rossi  mario  25, bianchi  luigi  55, verdi  mario  14, gialli  luigi  45, maffei  mario  32, servillo  luigi  56]

Ordinamento Naturale>>[bianchi  luigi  55, gialli  luigi  45, maffei  mario  32, rossi  mario  25, servillo  luigi  56, verdi  mario  14]

Ordinamento per età>>[verdi  mario  14, rossi  mario  25, maffei  mario  32, gialli  luigi  45, bianchi  luigi  55, servillo  luigi  56]














2 commenti:

  1. Ma se volessi utilizzare un oggetto comparator per scrivermi da me un algoritmo di ordinamento senza affidarmi ad uno già implementato come dovrei fare??
    Per esempio un metodo bubbleSort(Comparator) per una collezione Lista da voler usare magari su un'istanza concreta Lista...

    RispondiElimina
  2. Ciao, il Comparator serve soltanto a definire quale sarà il criterio di comparazione tra gli elementi.
    Il metodo Collections.sort, come si legge dal javadoc, utilizza il mergesort per l'ordinamento (più efficiente del bubble sort).
    Se quindi dovessi implementare un bubble sort senza affidarmi al default allora mi creerei una mia classe MyCollections con un metodo sort(List list,Comparator c) al cui interno implementerei la mia logica.

    RispondiElimina