Problema con ordinamento

di il
13 risposte

Problema con ordinamento

Salve a tutti,

ho un problema che non riesco a risolvere, spero che possiate aiutarmi.

Ho delle lettere che hanno una data invio e un livello di importanza, vorrei visualizzarle in una tabella ordinate per anno di invio e, a parità, per livello di importanza.

Ad esempio se ho e lettere con i seguenti parametri

lettera 1
data invio: 18-09-2013
livello di importanza: 5
------------------------------------
lettere 2
data Invio: 22-09-2013
livello di importanza: 7
------------------------------------
lettera 3
datainvio: 30-1-2016
livello di importanza: 10
------------------------------------

vorrei che fossero visualizzate in una tabella in questo ordine : lettera2-lettera1-lettera3

Dopo aver implementato la mia classe lettera con Comparable<Lettera>

ho scritto diversi metodi compareTo() ma nessuno ha sortito l'effetto sperato.

Qualcuno di voi potrebbe indirizzarmi sulla soluzione?

13 Risposte

  • Re: Problema con ordinamento

    CRTVLB ha scritto:


    Dopo aver implementato la mia classe lettera con Comparable<Lettera>

    ho scritto diversi metodi compareTo() ma nessuno ha sortito l'effetto sperato.
    Se la tua classe implementa Comparable<Lettera> allora il solo ed unico compareTo che devi implementare è:

    public int compareTo(Lettera altraLettera)
  • Re: Problema con ordinamento

    andbin ha scritto:


    Se la tua classe implementa Comparable<Lettera> allora il solo ed unico compareTo che devi implementare è:

    public int compareTo(Lettera altraLettera)
    ed è quello che ho fatto solo che non sono riuscito ad avere quello che speravo.

    Questo è l'ultimo tentativo che ho fatto
    
      public int compareTo(Lettera o) {
            int posizione = 0;
            if ((this.getDataInvio().YEAR == o.getDataInvio().YEAR) && (this.getLivelloBonta() > o.getLivelloBonta())){
                posizione = -1;
            }else if ((this.getDataInvio().YEAR == o.getDataInvio().YEAR) && (this.getLivelloBonta() < o.getLivelloBonta())){
                posizione = 1;
            }else {
                posizione = 0;
            }
            return posizione;
            
        }
    


    Ne ho scritti diversi di metodo compareTo(Lettera o) ma nessuno ha dato l'effetto sperato. Diciamo che se dovessi confrontare solo le date o solo i livelli di importanza non avrei problemi ma in questo caso, dovendoli confrontare insieme, non riesco a trovare il bandolo della matassa.
  • Re: Problema con ordinamento

    No infatti, non va bene, è contorto. Quando si devono fare confronti su più campi "in cascata", si deve ragionare come quando ad esempio si ordinano delle persone per cognome e poi per nome. Se già Bianchi viene prima di Rossi, NON hai bisogno di confrontare i nomi, sai già il risultato finale! Se invece sono entrambi Rossi, allora e solo allora vai a confrontare i nomi.

    Prova a pensarci.

    P.S. visto che i due campi che tratti sono int, puoi:
    - usare una catena di if-else
    - usare una catena di operatori condizionali ? :
    - sfruttare il compare statico di Integer

    Insomma, ci sono almeno 3 varianti possibili.
  • Re: Problema con ordinamento

    andbin ha scritto:



    P.S. visto che i due campi che tratti sono int, puoi:
    - usare una catena di if-else
    - usare una catena di operatori condizionali ? :
    - sfruttare il compare statico di Integer * Diciamo che sarei interessato ad usare questa come soluzione

    Insomma, ci sono almeno 3 varianti possibili.
    è da stamattina che ci penso, ma non ne sono venuto ancora a capo

    l'ultimo metodo scritto è questo:
    
    public int compareTo(Lettera o) {
          Integer a1 = livelloPriorità;
          Integer b1 = o.livelloPriorità;
          if (this.getDataInvio().YEAR < o.getDataInvio().YEAR) {
              return 1;
          }else if (this.getDataInvio().YEAR==o.getDataInvio().YEAR){
            return b1.compareTo(a1);//A parità di lunghezza ordino per livello di priorità
          }else{
              return -1;
          }
    
    Ma l'unica cosa che fa è ordinarmeli per livello di priorità e non prima per l'anno.

    Ho il dubbio he il problema sia proprio il confronto dell'anno.
  • Re: Problema con ordinamento

    CRTVLB ha scritto:


    è da stamattina che ci penso, ma non ne sono venuto ancora a capo

    l'ultimo metodo scritto è questo:
    
        public int compareTo(Lettera o) {
            if (getDataInvio().YEAR > o.getDataInvio().YEAR) {
                return -1;
            }else if (getDataInvio().YEAR == o.getDataInvio().YEAR) {
                 if(livelloPriorità > o.livelloPriorità) {
                     return -1;
                 }else {
                     return 1;
                 }
            }else { 
                return 1;
            }    
        }
    
    Ma l'unica cosa che fa è ordinarmeli per livello di priorità e non prima per l'anno.
    Innanzitutto, ovviamente, io non so al momento come è fatta la tua classe. Cosa restituisce getDataInvio() ? Cosa è YEAR?
    Perché già la forma getDataInvio().YEAR non è granché bella/esplicativa ...

    Se ci fossero, per ipotesi, i metodi int getAnnoInvio() e int getLivelloPriorita(), allora se vuoi ordinare:
    - per anno invio decrescente
    e poi
    - per livello priorità decrescente

    allora sarebbe corretto:
    public int compareTo(Lettera altraLettera) {
        if (getAnnoInvio() < altraLettera.getAnnoInvio()) {
            return +1;
        } else if (getAnnoInvio() > altraLettera.getAnnoInvio()) {
            return -1;
        } else if (getLivelloPriorita() < altraLettera.getLivelloPriorita()) {
            return +1;
        } else if (getLivelloPriorita() > altraLettera.getLivelloPriorita()) {
            return -1;
        } else {
            return 0;
        }
    }
    Che si può accorciare con l'operatore condizionale:
    public int compareTo(Lettera altraLettera) {
        return getAnnoInvio() < altraLettera.getAnnoInvio() ? +1 :
               getAnnoInvio() > altraLettera.getAnnoInvio() ? -1 :
               getLivelloPriorita() < altraLettera.getLivelloPriorita() ? +1 :
               getLivelloPriorita() > altraLettera.getLivelloPriorita() ? -1 : 0;
    }
  • Re: Problema con ordinamento

    La mia classe è questa:
    
    public class Lettera implements Comparable<Lettera> {
    
        private Calendar dataInvio = new GregorianCalendar();
        private int livelloPriorità;
    
        public Lettera() {
        }
    
        public Lettera( Calendar dataInvio, int livelloPriorità) {
            this.livelloPriorità = livelloPriorità;
            dataInvio.getTime();
            dataInvio.setLenient(false);
        }
    
        public Calendar getDataInvio() {
            return dataInvio;
        }
    
        public void setDataInvio(Calendar dataInvio) {
            this.dataInvio = dataInvio;
        }
    
        public int getLivelloPriorità() {
            return livelloPriorità;
        }
    
        public void setLivelloPriorità(int livelloPriorità) {
            this.livelloPriorità = livelloPriorità;
        }
    
        public String dataInvioFormattata() {
            Date d = dataInvio.getTime();
            SimpleDateFormat dataInvioFormattata = new SimpleDateFormat("EEEE dd-MMMM-yyyy");
            return dataInvioFormattata.format(d);
        }
        
        // CalcolaGiorni
        public long calcolaGiorni() {
           Date oggi = new Date();
           long giorni = (oggi.getTime() - dataInvio.getTime().getTime())    / (24 * 60 * 60 * 1000);
           return giorni;
        }
        
       
           
        public int compareTo(Lettera o) {
          Integer a1 = livelloPriorità;
          Integer b1 = o.livelloPriorità;
          if (this.getDataInvio().YEAR < o.getDataInvio().YEAR) {
              return 1;
          }else if (this.getDataInvio().YEAR==o.getDataInvio().YEAR){
            return b1.compareTo(a1);//A parità di anno ordino per livelloBonta
          }else{
              return -1;
          }
    
        }
         
    }
    
    Non ho una proprietà anno, quindi pensavo che tramite il metodo getDataInvio.YEAR potessi ricavami l'anno(probabilmente non è così ed è per questo che non riesco ad ordinarli come vorrei)
  • Re: Problema con ordinamento

    CRTVLB ha scritto:


        public Calendar getDataInvio() {
            return dataInvio;
        }
    Ah ... è un Calendar!! Allora YEAR è la costante di Calendar che indica l'indice del campo "anno" all'interno dell'oggetto Calendar.

    E quindi getDataInvio().YEAR semplicemente NON ha senso per i confronti.


    P.S. per essere sensato e funzionante, dovrebbe essere come minimo:

    getDataInvio().get(Calendar.YEAR)

    ma a quel punto, meglio definire un getAnnoInvio() per accorciare.
  • Re: Problema con ordinamento

    andbin ha scritto:




    P.S. per essere sensato e funzionante, dovrebbe essere come minimo:

    getDataInvio().get(Calendar.YEAR)
    Grazie mille adesso funziona correttamente
  • Re: Problema con ordinamento

    Scrivo qui per aggangiarmi al probleme precedente.

    Sto implementando l'esercizio ed ora la lettera ha anche una data di invio, una di scadenza e uno stato che può essere scaduto se la data di scadenza è precedente ad oggi, in scadenza se la data di scadenza e da qui ad un mese e in corse se la data di scadenza supere un mese.

    googlando un po' sono riuscito a scrivere questo metodo, che funziona correttamente ma che non ho capito fino in fondo:
    
    public String statoMemo() {
            String stato = "";
            Calendar oggi = new GregorianCalendar();
            Calendar unMeseDaOggi = new GregorianCalendar();
            unMeseDaOggi.set(2,unMeseDaOggi.get(Calendar.MONTH)+1);
            if(this.dataSca.before(oggi)){
                stato = "scaduta";
            }else if(this.getDataSca().before(unMeseDaOggi)){
                stato = "inscadenza";
            }else if(this.dataSca.after(oggi)){
                stato = "incorso";
            }
            return stato;
        }
    
    In particolare quello che non mi è chiaro è

    unMeseDaOggi.set(2,unMeseDaOggi.get(Calendar.MONTH)+1);

    cosa mi sta a significare quel 2? qualcuno potrebbe spiegarmelo?
  • Re: Problema con ordinamento

    CRTVLB ha scritto:


    In particolare quello che non mi è chiaro è

    unMeseDaOggi.set(2,unMeseDaOggi.get(Calendar.MONTH)+1);

    cosa mi sta a significare quel 2? qualcuno potrebbe spiegarmelo?
    Quello è il:

    public void set(int field, int value)

    Dove 'field' è l'indice dell'elemento nel Calendar. E quel 2 in realtà andrebbe scritto Calendar.MONTH, principalmente per chiarezza.

    E che comunque è da prendere con le pinze, perché ad esempio se sei al 30 Gennaio, quel +1 sul mese ti fa andare al 1 Marzo !
  • Re: Problema con ordinamento

    Grazie mille quindi, in teoria, anche se con tutte le prove che ho fatto mi ha sempre funzionato ci saranno dei casi particolari in cui il risultato sarà sballato?

    Quale sarebbe il modo più corretta per fare la verifica se la mia lettera è scaduta, in corso o in scadenza?
  • Re: Problema con ordinamento

    CRTVLB ha scritto:


    Quale sarebbe il modo più corretta per fare la verifica se la mia lettera è scaduta, in corso o in scadenza?
    Dipende cosa si vuole intendere per "un mese". Se vuoi intendere 30 giorni (valore tipico/medio), basta usare il add e aggiungere (sul campo DAY_OF_MONTH) appunto 30 giorni. Questo risulterà sempre corretto, indipendentemente dal giorno di partenza.
  • Re: Problema con ordinamento

    No il mio obbiettivo è proprio quello di evidenziare una lettera che scade nel mese successivo, sia che siamo al 1 gennaio sia che siamo al 30 e cosi via per tutti i mesi.
Devi accedere o registrarti per scrivere nel forum
13 risposte