Esercizio Java con array dinamici

di il
6 risposte

Esercizio Java con array dinamici

Buongiorno a tutti, mi sono imbattuto in un esercizio Java apparentemente facile, ma non riesco a venirne a capo in un punto.
Il testo dell'esercizio è il seguente: "Dopo aver caricato in un vettore le temperature rilevate in una settimana, cancellare la temperatura massima e la minima.". Non riesco a fare confronti tra array dinamici. Qualcuno mi puo dare una mano a capire dove sto sbagliando?

Questo è quanto ho fatto fin'ora:


package progtemperatura;
import java.io.*;

public class Temp {
    private String citta;
    private float temperatura;
    
    public Temp(){
        InputStreamReader input=new InputStreamReader(System.in);
        BufferedReader tastiera=new BufferedReader(input);
        String t=new String();
        System.out.println("Inserire la citta: ");
        try{
            citta=tastiera.readLine();
        }
        catch(IOException e){}
        
        System.out.println("Inserire la temperatura: ");
        try{
            t=tastiera.readLine();
            temperatura=Float.valueOf(t).floatValue();
        }
        catch(Exception e){}
    }
    
    public void print(){
        System.out.println("Citta': "+citta);
        System.out.println("Temperatura: "+temperatura);
    }
}


package progtemperatura;
import java.util.Vector;

public class Inserimento {
    private Vector elenco;
    
    public Inserimento(){
        elenco=new Vector(1, 1);
    }
    
    public void add(Temp a){
        elenco.addElement(a);
    }
    
    public void delete(int indice){
        try{
            elenco.removeElementAt(indice);
        }
        catch(Exception e){
            System.out.println("Eliminazione non possibile");
        }
        
        System.out.println("Eliminazione effettuata.");
    }
    
    public int tempMax(){
        int indiceMax=0;
         
        Temp max=(Temp)elenco.elementAt(0);
        
        for(int i=0; i<elenco.size(); i++){
            if((Temp)elenco.elementAt(i)<max){
                max=(Temp)elenco.elementAt(i);
                indiceMax=i;
            }
        }
        return indiceMax;
    }
    
    public int tempMin(){
        int indiceMin=0;
        Temp min=(Temp) elenco.elementAt(0);
        
        for(int i=0; i<elenco.size(); i++){
            if((Temp)elenco.elementAt(i)<min){
                min=(Temp)elenco.elementAt(i);
                indiceMin=i;
            }
        }
        return indiceMin;
    }
    
    public void visualizza(){
        Temp a;
        System.out.println("\nTEMPERATURE: ");
        for(int i=0; i<elenco.size(); i++){
            System.out.println("POSIZIONE: "+i+"->");
            a=(Temp)elenco.elementAt(i);
            a.print();
        }
    }
}



package progtemperatura;

public class Menu {
    private void mostraMenu(){
        System.out.println();
        System.out.println("1) Aggiungi temperatura");
        System.out.println("2) Elimina temperatura");
        System.out.println("3) Visualizza temperature");
        System.out.println("4) Esci");
    }
    
    public int scelta(){
        InputStreamReader input=new InputStreamReader(System.in);
        BufferedReader tastiera=new BufferedReader(input);
        int scelta;
        
        mostraMenu();
        System.out.println("->");
        try{
            String numeroLetto=tastiera.readLine();
            scelta=Integer.valueOf(numeroLetto).intValue();
        }
        catch(Exception e){
            scelta=0;
        }
        return scelta;
    }
    
    public int leggiIndice(){
        InputStreamReader input=new InputStreamReader(System.in);
        BufferedReader tastiera=new BufferedReader(input);
        int indice;
        
        System.out.print("\nVoce da eliminare: ");
        try{
            String numeroLetto=tastiera.readLine();
            indice=Integer.valueOf(numeroLetto).intValue();
        }
        catch(Exception e){
            indice=-1;
        }
        return indice;
    }
    
}


package progtemperatura;


public class ProgTemperatura {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Inserimento ins =new Inserimento();
        Menu azione=new Menu();
        int scelta=0;
        
        while(scelta!=4){
            if(scelta==1){
                Temp a=new Temp();
                ins.add(a);
            }
            else if(scelta==2){
                //int indice=azione.leggiIndice();
                //ins.delete(indice);
                int max=ins.tempMax();
                //int min=ins.tempMin();
                ins.delete(max);
                //ins.delete(min);
            }
            else if(scelta==3){
                ins.visualizza();
            }
            scelta=azione.scelta();
        }
        System.out.println("Fine programma.");
        
        
    }
    
}

6 Risposte

  • Re: Esercizio Java con array dinamici

    Ci sono diverse cose non vanno.
    Innanzitutto, è dal 2004 (con l'uscita della versione 5 di Java) che sono stati introdotti i Generics e tutte le classi del framework standard (ove necessario, ovviamente) sono state rese generiche. Vector è una di quelle.
    Quindi, per istanziare un oggetto Vector bisogna anche tipizzarlo.
    Nel tuo caso, stai usando un Vector per contenere oggetti di tipo Temp (tralasciamo per il momento la nomenclatura), quindi:
    
    Vector<Temp> elenco;
    ...
    elenco = new Vector<Temp>();
    
    // Da Java 7 puoi anche usare l'operatore diamond (sarà il compilatore ad inferire il tipo corretto):
    elenco = new Vector<>();
    
    Questo ti evita di dover fare un cast ogni volta che tiri fuori un oggetto dal Vector:
    
    Temp tmp = elenco.elementAt( i );
    
    Altra cosa: nella classe Temp stai facendo I/O. Non è corretto sotto ogni punto di vista. L'I/O dovrebbe essere fatto in una classe separata dal bean che contiene i dati. Così ottieni una migliore separazione dei ruoli delle classi (e ti eviti un sacco di problemi).

    Veniamo al problema principale: la variabile "max" del metodo tempMax è di tipo Temp. Fin qui tutto ok. Il problema sorge, appunto nel confronto... non puoi confrontare due oggetti usando gli operatori relazionali: quelli li puoi usare solo per le variabili numeriche. Ciò che devi confrontare, infatti, non sono gli oggetti, ma i valori in essi contenuti. E come puoi farlo? Al momento non puoi: i valori dell'oggetto Temp sono privati (ed è corretto che sia così) e non hai alcun modo di accedervi.
    Devi implementare (almeno) i metodi getter nella classe Temp per poter ottenere i valori dell'oggetto. Poi confronterai i valori numerici.
    In realtà, per quanto detto prima (non fare I/O nell'oggetto Temp) dovrai implementare anche i setter o, quantomento, un costruttore in grado di riceverne i valori.
  • Re: Esercizio Java con array dinamici

    SpiritoLibero ha scritto:


    Ci sono diverse cose non vanno.
    Innanzitutto, è dal 2004 (con l'uscita della versione 5 di Java) che sono stati introdotti i Generics e tutte le classi del framework standard (ove necessario, ovviamente) sono state rese generiche. Vector è una di quelle.
    Quindi, per istanziare un oggetto Vector bisogna anche tipizzarlo.
    Nel tuo caso, stai usando un Vector per contenere oggetti di tipo Temp (tralasciamo per il momento la nomenclatura), quindi:
    
    Vector<Temp> elenco;
    ...
    elenco = new Vector<Temp>();
    
    // Da Java 7 puoi anche usare l'operatore diamond (sarà il compilatore ad inferire il tipo corretto):
    elenco = new Vector<>();
    
    Questo ti evita di dover fare un cast ogni volta che tiri fuori un oggetto dal Vector:
    
    Temp tmp = elenco.elementAt( i );
    
    Altra cosa: nella classe Temp stai facendo I/O. Non è corretto sotto ogni punto di vista. L'I/O dovrebbe essere fatto in una classe separata dal bean che contiene i dati. Così ottieni una migliore separazione dei ruoli delle classi (e ti eviti un sacco di problemi).

    Veniamo al problema principale: la variabile "max" del metodo tempMax è di tipo Temp. Fin qui tutto ok. Il problema sorge, appunto nel confronto... non puoi confrontare due oggetti usando gli operatori relazionali: quelli li puoi usare solo per le variabili numeriche. Ciò che devi confrontare, infatti, non sono gli oggetti, ma i valori in essi contenuti. E come puoi farlo? Al momento non puoi: i valori dell'oggetto Temp sono privati (ed è corretto che sia così) e non hai alcun modo di accedervi.
    Devi implementare (almeno) i metodi getter nella classe Temp per poter ottenere i valori dell'oggetto. Poi confronterai i valori numerici.
    In realtà, per quanto detto prima (non fare I/O nell'oggetto Temp) dovrai implementare anche i setter o, quantomento, un costruttore in grado di riceverne i valori.
    Grazie per la risposta.
    Tralasciando un momento la questione relativa ai Generics introdotti da java 5 e 7, siccome sono alle prime armi con Java, vorrei soffermarmi su come sto svolgendo l'esercizio.
    Tu mi hai suggerito di creare il metodo getter per ritornare il valore della temperatura, ma non riesco a coglierne l'utilità. Questo lo facevo quando mi esercitavo con gli array normali, ma quì ho un array dinamico, come faccio scansionare il vector con il ciclo for? Non ho una siturazione del genere:
    
    //esempio
    int a=vet[0].getTemp();
    for(int i=0; i<10; i++){
    	if(vet[i].getTemp()>a){
    	a=vet[i].getTemp();
    	}
    
  • Re: Esercizio Java con array dinamici

    Il fatto che tu abbia un Vector, piuttosto che una List, piuttosto che una mappa o qualsiasi altra cosa che ti permette di gestire una "collezione" di oggetti, non c'entra nulla con il design della classe bean (oggetto contenitore di dati).

    Una classe bean (o, banalmente, un contenitore di dati) è una classe che deve permettere di assegnarle dei valori e deve permettere di leggere questi valori (tralasciamo, per il momento, discorsi più "complessi" su classi immutabili o altro).

    Come fa una classe a permettere che le vengano assegnati dei valori? Ci sono tre strade:
    1 - La classe mette a disposizione un costruttore che accetta tali valori
    2 - La classe espone dei metodi (setter) per permettere l'assegnazione di tali valori
    3 - (pessimissima) La classe rende pubblici i suoi campi

    Come fa una classe a permettere di leggere i propri valori? Ci sono solo due strade:
    1 - La classe espone dei metodi (getter) per permettere di "restituire" tali valori all'esterno
    2 - (pessimissima) La classe rende pubblici i suoi campi

    Quello che devi fare tu è confrontare le temperature. La temperatura è una delle informazioni che sono incapsulate nella classe Temp. Come fai a confrontare le temperature se non le puoi leggere? Risposta: non lo puoi fare (in realtà lo potresti anche fare, ma eventualmente questo lo vediamo in un secondo momento).

    Quindi, per prima cosa, sistemiamo il design di quella classe Temp e permettiamo al mondo esterno di usarla Dovrai, almeno, fornire il metodo getter per poter leggere la temperatura. Diciamo, quindi, che hai creato il metodo getTemperatura() che restituisce la temperatura. Ora puoi confrontare le temperature:
    
    Temp max = elenco.elementAt(0);
    for(int i=0; i<elenco.size(); i++) {
       if (elenco.elementAt(i).getTemperatura() > max.getTemperatura()) {
          max = elenco.elementAt(i);
          indiceMax = i;
       }
    }
    
  • Re: Esercizio Java con array dinamici

    Esistono anche altri modi per poter ottenere un confronto fra due oggetti senza per forza avere informazioni sul loro stato interno (ma, ripeto, non ne vedo l'utilità in questo frangente se non a scopo semplicemente informativo). Me ne vengono in mente 2:

    1 - Rendere la classe Temp "confrontabile": implementare, quindi, un meccanismo che permetta di confrontare due oggetti Temp facendo in modo di definire un loro ordinamento "naturale". Questo è utile in moltissime situazioni, soprattutto quando si vogliono utilizzare algoritmi di ordinamento tra oggetti. La "pecca" di questo sistema è che l'informazione sulla quale viene fatto l'ordinamento è prefissata e non può essere modificata (se voglio poter confrontare due oggetti secondo un altro dei suoi valori non lo posso fare).

    2 - Creare un oggetto "confrontatore" che sia in grado, presi due oggetti Temp, di dire se il primo è "minore", "maggiore" o "uguale" al secondo. Ma questo impone di avere una classe Temp che permetta di essere letta, quindi si torna a quanto detto precedentemente e alla necessità di avere i metodi getter.

    Per implementare il punto 1 dobbiamo far sì che la classe esponga un metodo che riceve un'istanza di Temp e ne confronti lo stato interno (la classe Temp ha accesso diretto a tutti i campi, anche privati, di qualsiasi altra istanza di sé stessa). Esiste un'apposita interfaccia che serve a denotare classi che possono essere confrontate tra di loro, così da uniformare il comportamento. Tale interfaccia si chiama Comparable (è anch'essa generica) e obbliga ad implementare un metodo che si chiama "compareTo()" che riceve un oggetto della classe stessa:
    
    public class Temp implements Comparable<Temp> {
       ...
       private int temperatura;
       ...
    
       @Override
       public int compareTo(Temp t) {
          int ret = 0;
          int confronto = temperatura - t.temperatura;
          if (confronto > 0) {
             ret = 1;
          }
          if (confronto < 0) {
             ret = -1;
          }
          return ret;
       }
    }
    
    In questo modo possiamo sfruttare tale metodo per effettuare i confronti tra gli oggetti:
    
    Temp max = elenco.elementAt(0);
    for(int i=0; i<elenco.size(); i++) {
       if (max.compareTo(elenco.elementAt(i)) < 0) {
          // max è più piccolo dell'i-esimo elemento
          max = elenco.elementAt(i);
       }
    }
    
    Ripeto, comunque, che una classe senza metodi getter (a meno che non abbia campi pubblici o non sia specificatamente disegnata per fare cose diverse da "contenere dati") non ha alcun senso di esistere perchè sarebbe totalmente inutilizzabile dal resto dell'applicazione.
  • Re: Esercizio Java con array dinamici

    SpiritoLibero ha scritto:


    Il fatto che tu abbia un Vector, piuttosto che una List, piuttosto che una mappa o qualsiasi altra cosa che ti permette di gestire una "collezione" di oggetti, non c'entra nulla con il design della classe bean (oggetto contenitore di dati).

    Una classe bean (o, banalmente, un contenitore di dati) è una classe che deve permettere di assegnarle dei valori e deve permettere di leggere questi valori (tralasciamo, per il momento, discorsi più "complessi" su classi immutabili o altro).

    Come fa una classe a permettere che le vengano assegnati dei valori? Ci sono tre strade:
    1 - La classe mette a disposizione un costruttore che accetta tali valori
    2 - La classe espone dei metodi (setter) per permettere l'assegnazione di tali valori
    3 - (pessimissima) La classe rende pubblici i suoi campi

    Come fa una classe a permettere di leggere i propri valori? Ci sono solo due strade:
    1 - La classe espone dei metodi (getter) per permettere di "restituire" tali valori all'esterno
    2 - (pessimissima) La classe rende pubblici i suoi campi

    Quello che devi fare tu è confrontare le temperature. La temperatura è una delle informazioni che sono incapsulate nella classe Temp. Come fai a confrontare le temperature se non le puoi leggere? Risposta: non lo puoi fare (in realtà lo potresti anche fare, ma eventualmente questo lo vediamo in un secondo momento).

    Quindi, per prima cosa, sistemiamo il design di quella classe Temp e permettiamo al mondo esterno di usarla Dovrai, almeno, fornire il metodo getter per poter leggere la temperatura. Diciamo, quindi, che hai creato il metodo getTemperatura() che restituisce la temperatura. Ora puoi confrontare le temperature:
    
    Temp max = elenco.elementAt(0);
    for(int i=0; i<elenco.size(); i++) {
       if (elenco.elementAt(i).getTemperatura() > max.getTemperatura()) {
          max = elenco.elementAt(i);
          indiceMax = i;
       }
    }
    
    Perfetto adesso mi trovo, anche ci avevo provato prima ma non mi trovava il metodo getTemp().
    Quindi funziona solo se imposto il vector come mi hai detto di fare tu:
    
     private Vector<Temp>elenco;
     elenco=new Vector<Temp>(1, 1);
     
    Se invece continuo come lo avevo impostato io non funziona.
    
    //così non funziona
    int indiceMax=0;
             
            Temp max=(Temp)elenco.elementAt(0);
            
            for(int i=0; i<elenco.size(); i++){
                if((Temp)elenco.elementAt(i).(non trova nulla)<max.getTemp()){ 
                    max=(Temp)elenco.elementAt(i);
                    indiceMax=i;
                }
            }
            return indiceMax;
        }
    
  • Re: Esercizio Java con array dinamici

    Questo perchè è necessario usare le parentesi tonde in modo "più appropriato": l'operatore di indirezione (il punto) ha precedenza sul cast.
    
            for(int i=0; i<elenco.size(); i++){
                if(( (Temp)elenco.elementAt(i) ).getTemp()<max.getTemp()){ 
                    max=(Temp)elenco.elementAt(i);
                    indiceMax=i;
                }
            }
    
    Nota che l'espressione col cast è inclusa dentro alle tonde. Così funziona perchè in questo modo sto dando precedenza al cast rispetto all'operatore "punto" (la spaziatura dentro alle tonde non serve, l'ho messa io per evidenziare).
Devi accedere o registrarti per scrivere nel forum
6 risposte