Conta per ogni elemento della lista

di il
36 risposte

36 Risposte - Pagina 2

  • Re: Conta per ogni elemento della lista

    Scusami ancora se ti disturbo ma mi spiego meglio.

    Io ho 3 classi, una classe agenzia dove ho una listaViaggi e una listaClienti

    Poi la classe Cliente con attributi: nome, cognome, codice fiscale e una lista di viaggi

    La classe Viaggio con Data e Luogo.

    Nella classe Agenzia,ho aggiunto il metodo per contare quanti viaggi sono stati fatti in una determinata localita, in questo modo:
    
    public Map<String,Integer> getConteggioViaggiPerLuoghi() {
            Map<String,Integer> mappaConteggi = new HashMap<String,Integer>();
    
            for (Viaggio viaggio : listaViaggi) {
                String luogo = viaggio.getLuogoViaggio();
                Integer conteggio = mappaConteggi.get(luogo);
                mappaConteggi.put(luogo, conteggio == null ? 1 : conteggio+1);
            }
        
            return mappaConteggi;
        }
    
    Ora vorrei che cliccando su un pulsante mi si aprisse una nuova jDialog con una tabella e con scritto ad esempio:

    Luogo Viaggio| Numero Viaggi
    Parigi | 2
    Berlino | 3

    e cosi via.

    Il miei dubbi sono:

    Come imposto il modelloTabella ?

    nella JDialog dove visualizzo la tabella con i dati come scrivo il metodo che inizializza la tabella?

    io avevo pensato a questo:
    
    private void inizializzaTabellaContaViaggi() {
            Agenzia agenzia = (Agenzia) this.vista.getModello().getBean(Costanti.AGENZIA);
            if ( agenzia == null ) {
                this.visualizzaFinestraErrore(" Errore inizializzazione ----Non è stato possibile inizializzare la Tabella");
            }else{
            ModelloTabellaContaViaggi mtcv = new ModelloTabellaContaViaggi(agenzia);
            this.tabellaContaViaggi.setModel((TableModel)mtcv);
            this.scrollTabellaContaViaggi.setViewportView(tabellaContaViaggi);
             }
        }
    
    Mentre il modelloTabella in questo modo:
    
    public class ModelloTabellaContaViaggi extends AbstractTableModel {
            private Agenzia agenzia;
            private List<Agenzia> listaConteggioPerLuogo;
        
    
        public ModelloTabellaContaViaggi(Agenzia agenzia) {
           this.agenzia = agenzia;
        }
        
        public int getRowCount() {
            return // qui come faccio a sapere qual'è la lunghezza della lista?
        }
    
        public int getColumnCount() {
            return 2;
        }
    
        public Object getValueAt(int r, int c) {
            Agenzia agenzia = listaConteggioPerLuogo.get(r);
    
            if (c == 0) {
               return // come faccio a dirgli che deve darmi il nome del luogo?
            } else if (c == 1) {
               return // stesso problema con il numero dei viaggi effettuati verso quel luogo
            }
    
            return null;  
        }
        
            @Override
        public String getColumnName(int c) {
            if (c == 0) {
                return "Luogo Avvistamento";
            }else if (c == 1) {
                return "Numero Avvistamenti";
            }
            return null;
        }
    
    
    Ecco quello che ti chiedo è possibile fare quello che voglio in questo modo o mi servono altri metodi?

    P.s. spero di essere stato più chiaro questa volta.
  • Re: Conta per ogni elemento della lista

    CRTVLB ha scritto:


    public Map<String,Integer> getConteggioViaggiPerLuoghi() {
    
    Un Map<String,Integer> comunque non è granché utile per un table model. Non basta. Serve una struttura più lineare e indirizzata per indice.

    CRTVLB ha scritto:


    Come imposto il modelloTabella ?
    L'ho spiegato nel mio post precedente, mostrando un abbozzo di table model.

    CRTVLB ha scritto:


    Agenzia agenzia = (Agenzia) this.vista.getModello().getBean(Costanti.AGENZIA);
    È un pochettino "brutta" (non troppo comunque) una gestione degli oggetti di questo tipo.

    CRTVLB ha scritto:


    Mentre il modelloTabella in questo modo:
    
    public class ModelloTabellaContaViaggi extends AbstractTableModel {
            private Agenzia agenzia;
            private List<Agenzia> listaConteggioPerLuogo;
        
    
        public ModelloTabellaContaViaggi(Agenzia agenzia) {
           this.agenzia = agenzia;
        }
    Ripeto che molto probabilmente avere Agenzia nel modello è poco utile. A meno che ci siano cose della tua applicazione che chiaramente non posso conoscere io.

    E quale sia il senso di un

    List<Agenzia> listaConteggioPerLuogo

    non lo so .....
  • Re: Conta per ogni elemento della lista

    Ho risolto in questo modo, mi funziona tutto perfettamente ma volevo chiederti se è la soluzione giusta o se ne esiste un'altra migliore:

    // metodo che conta quanti viaggi ci sono verso una località già presente nell'agenzia.
    
    public Map<String, Integer> getConta() {
            Map<String, Integer> risultato = new HashMap<String, Integer>();
           
                for (Viaggio viaggio : this.getListaViaggi()) {
                    String luogo = viaggio.getLuogoViaggio();
                    if (risultato.containsKey(luogo)) {
                        Integer vecchioValore = risultato.get(luogo);
                        vecchioValore++;
                        risultato.put(luogo, vecchioValore);
                    } else {
                        risultato.put(luogo, 1);
                    }
                }
            
            return risultato;
        }
    
    // inizializzazione della Tabella
    
    private void inizializzaTabellaConta() {
            Agenzia agenzia = (Agenzia) this.vista.getModello().getBean(Costanti.Agenzia);
            if ( agenzia == null ) {
                this.visualizzaFinestraErrore(" Errore inizializzazione----Non è stato possibile inizializzare la Tabella");
            }else{
            ModelloTabellaConta mtc = new ModelloTabellaConta(agenzia.getConta());
            this.tabellaConta.setModel((TableModel)mtc);
            this.scrollTabellaContaA.setViewportView(tabellaConta);
             }
        }
    
    // Modello Tabella
    
     public class ModelloTabellaConta extends AbstractTableModel {
            private Map<String,Integer> mappa;
            private List<String> listaCitta;
    
        public ModelloTabellaConta(Map<String, Integer> mappa) {
            this.mappa = mappa;
            listaCitta = new ArrayList<String>(mappa.keySet());
        }
      
        public int getRowCount() {
            return mappa.size();
        }
    
        public int getColumnCount() {
            return 2;
        }
    
        public Object getValueAt(int r, int c) {
            if (c == 0) {
               return listaCitta.get(r);
            } else if (c == 1) {
               return mappa.get(listaCitta.get(r));
            }
    
            return null;  
        }
        
            @Override
        public String getColumnName(int c) {
            if (c == 0) {
                return "Luogo Viaggio";
            }else if (c == 1) {
                return "Numero Viaggi";
            }
            return null;
        }
    
    }
    
  • Re: Conta per ogni elemento della lista

    CRTVLB ha scritto:


    
    public Map<String, Integer> getConta() {
            Map<String, Integer> risultato = new HashMap<String, Integer>();
           
                for (Viaggio viaggio : this.getListaViaggi()) {
                    String luogo = viaggio.getLuogoViaggio();
                    if (risultato.containsKey(luogo)) {
                        Integer vecchioValore = risultato.get(luogo);
                        vecchioValore++;
                        risultato.put(luogo, vecchioValore);
                    } else {
                        risultato.put(luogo, 1);
                    }
                }
            
            return risultato;
        }
    
    È un pochettino più lungo del mio e leggermente più inefficiente (fai containsKey oltre che get). Non sono comunque problemi davvero rilevanti e funzionalmente è uguale al mio.

    In questo caso il containsKey non servirebbe, potresti abbreviarlo un po' così:
    public Map<String, Integer> getConta() {
        Map<String, Integer> risultato = new HashMap<String, Integer>();
    
        for (Viaggio viaggio : this.getListaViaggi()) {
            String luogo = viaggio.getLuogoViaggio();
            Integer contatore = risultato.get(luogo);
    
            if (contatore != null) {
                risultato.put(luogo, contatore + 1);
            } else {
                risultato.put(luogo, 1);
            }
        }
    
        return risultato;
    }
    Che è comunque leggibilissimo. Non è possibile che un value sia null. Quindi null vuol solo dire che la chiave non c'è.

    CRTVLB ha scritto:


    
            ModelloTabellaConta mtc = new ModelloTabellaConta(agenzia.getConta());
            this.tabellaConta.setModel((TableModel)mtc);
    Il cast a TableModel NON serve. ModelloTabellaConta è-un TableModel.

    CRTVLB ha scritto:


    
     public class ModelloTabellaConta extends AbstractTableModel {
            private Map<String,Integer> mappa;
            private List<String> listaCitta;
    
        public ModelloTabellaConta(Map<String, Integer> mappa) {
            this.mappa = mappa;
            listaCitta = new ArrayList<String>(mappa.keySet());
        }
      //.................
    
    Tecnicamente è corretto. Ma è un pochino contorto, in particolare il getValueAt. Funziona di certo ma ci sono due cose che devi considerare:
    - l'ordinamento dei luoghi dipende solo dalla implementazione della mappa. Avendo usato HashMap non c'è un ordine garantito/prevedibile. Una soluzione banale sarebbe ordinare il listaCitta nel costruttore.

    - se dovessi aggiungere altre informazioni, es. una terza colonna (per dire: il numero di viaggi nel solo anno corrente), saresti nei casini e complicheresti solo le cose. Per questo motivo, avere una classe "bean" che rappresenta una riga di informazione, generalmente è soluzione più pulita.
  • Re: Conta per ogni elemento della lista

    Scusami ancora e se invece volessi trovare per ogni viaggio quello col prezzoMassimo

    ad esempio io ho 2 viaggi per parigi uno dal costo di 120 ed uno 100, 3 verso berlino con costi 99-150-195.

    Come faccio a fare la stessa cosa ma invece di un conta mi restituisce il prezzo massimo in questo modo:

    parigi 120
    Berlino 195

    ho provato ad adattare il metodo conta ma la mappa me la restituisce vuota.
  • Re: Conta per ogni elemento della lista

    CRTVLB ha scritto:


    Come faccio a fare la stessa cosa ma invece di un conta mi restituisce il prezzo massimo in questo modo:

    parigi 120
    Berlino 195

    ho provato ad adattare il metodo conta ma la mappa me la restituisce vuota.
    La struttura è simile al metodo di conteggio che abbiamo (io e te) mostrato. Ma con 2 differenze:

    - il value della mappa è il valore massimo "corrente", non più un contatore.
    - il put non lo devi fare sempre ma solo in uno di questi casi: non c'è la chiave nella mappa (cioè il primo prezzo per un luogo è il massimo corrente) OPPURE il prezzo del viaggio è maggiore di quello corrente.

    Sono due condizioni in OR e pertanto nel ciclo bastano: un get, un if con le due condizioni e un put dentro il if. Tutto qui.
  • Re: Conta per ogni elemento della lista

    Ok grazie ancora,

    appena ho un po' di tempo cerco di riscrivere il codice seguendo i tuoi consigli.
  • Re: Conta per ogni elemento della lista

    Ho provato in diversi modi ma la mappa me la restituisce sempre null.

    Mi potresti dire come fare?
  • Re: Conta per ogni elemento della lista

    CRTVLB ha scritto:


    Mi potresti dire come fare?
    Ma il prezzo dove è? In Viaggio? Quello che avevi mostrato non ce l'ha (secondo tuo post).
  • Re: Conta per ogni elemento della lista

    Per esercitarmi ho ampliato la classe viaggio che ora ha anche un attributo prezzo
    
    public class Viaggio implements Comparable <viaggio> {
       
        private String luogoViaggio;
        private Calendar data = new GregorianCalendar();
        private int prezzo;
       
        public Viaggio() {}
       
        public Viaggio(Calendar data, String luogoViaggio, Int prezzo) {
            this.luogoViaggio = luogoViaggio;
            this.data = data;
            this.prezzo = prezzo:
            data.getTime();
            data.setLenient(false);
        }
       
        public String getLuogoViaggio() {
            return luogoViaggio;
        }
    
        public void setLuogoViaggio(String luogoViaggio) {
            this.luogoViaggio = luogoViaggio;
        }
    
        public int getPrezzo() {
            return prezzo;
        }
    
        public void setPrezzo(int prezzo) {
            this.prezzo = prezzo;
        }
    
        public Calendar getData() {
            return data;
        }
    
        public void setData(Calendar data) {
            this.data = data;
        }
       
        public String toStringData() {
            Date d = data.getTime();
            SimpleDateFormat giorno = new SimpleDateFormat("EEEE dd-MMMM-yyyy");
            return giorno.format(d);
        }
       
        @Override
        public String toString() {
            String stringa = "";
            stringa += "Luogo" + luogoViaggio +"\n";
            stringa += "Data " + data +"\n";
            stringa += "Prezzo" + prezzo +"\n";
            return stringa;
        }
    
        public int compareTo(Avvistamento o) {
            return getData().compareTo(o.getData());
        }
    
  • Re: Conta per ogni elemento della lista

    public Map<String,Integer> getPrezzoMassimoViaggiPerLuoghi() {
        Map<String,Integer> mappaPrezziMassimi = new HashMap<String,Integer>();
    
        for (Viaggio viaggio : listaViaggi) {
            String luogo = viaggio.getLuogoViaggio();
            Integer prezzoMassimo = mappaPrezziMassimi.get(luogo);
            
            if (prezzoMassimo == null || viaggio.getPrezzo() > prezzoMassimo) {
                mappaPrezziMassimi.put(luogo, viaggio.getPrezzo());
            }
        }
    
        return mappaPrezziMassimi;
    }
    Cosa ti dicevo infatti? 1 get, 1 if (2 condizioni), 1 put

    P.S. scritto al volo, corretto salvo miei errori di scrittura.
  • Re: Conta per ogni elemento della lista

    Ti ringrazio funziona benissimo!

    Adesso che l'ho visto non capisco come non ci ho fatto ad arrivare da solo

    Scusami ma ora però mi è venuto un altro dubbio.

    Mettiamo che io voglia aggiungere un attributo nomeViaggio alla classe viaggio

    Ad esempio avrò

    Luogo: Parigi
    Nome viaggio: 3 giorni 2 notti
    prezzo: 160 euro
    -----------------------------------------
    Luogo: Parigi
    Nome viaggio: Capodanno a Parigi
    prezzo: 190 euro
    -----------------------------------------
    Luogo: Parigi
    Nome viaggio: 7 giorni 6 notti
    prezzo: 540
    -----------------------------------------
    Luogo: Berlino
    Nome viaggio: Weekend a Berlino
    prezzo: 110 euro
    -----------------------------------------
    Luogo: Berlino
    Nome viaggio: Hotel + Visita
    prezzo: 350 euro
    ----------------------------------------

    Come faccio a trovare sempre il massimo ma poi visualizzarlo nella Tabella in questo modo:

    Parigi | 7 giorni 6 notti| 540
    Berlino| Hotel + Visita | 350

    Non basta più una sola mappa o sbaglio?
  • Re: Conta per ogni elemento della lista

    CRTVLB ha scritto:


    Non basta più una sola mappa o sbaglio?
    Il mio era ovviamente un esempio. Visto che qui si cerca il viaggio con prezzo massimo, è assolutamente lecito e sensato un Map<String,Viaggio> !! Dove il value è appunto il Viaggio con prezzo massimo.

    In effetti non ci avevo pensato prima, volevi solo il prezzo.
  • Re: Conta per ogni elemento della lista

    andbin ha scritto:


    Il mio era ovviamente un esempio. Visto che qui si cerca il viaggio con prezzo massimo, è assolutamente lecito e sensato un Map<String,Viaggio> !! Dove il value è appunto il Viaggio con prezzo massimo.

    In effetti non ci avevo pensato prima, volevi solo il prezzo.
    Ti sarebbe possibile farmi un esempio? così lo capisco meglio.
  • Re: Conta per ogni elemento della lista

    CRTVLB ha scritto:


    Ti sarebbe possibile farmi un esempio?
    Esempio? Ma è pieno di esempi questo thread!

    Comunque quando fai un get ottieni un Viaggio (null se non c'è nella mappa), il put lo fai del Viaggio i-esimo (dal for) e basta correggere il confronto del prezzo perché ora hai 2 Viaggio di cui confrontare i prezzi.
Devi accedere o registrarti per scrivere nel forum
36 risposte