Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 12
  1. #1
    Utente di HTML.it
    Registrato dal
    Nov 2003
    Messaggi
    178

    [Java] problema con mappe

    Salve a tutti
    ho sviluppato un semplice programma che utilizza una hashmap popolandola di oggetti che hanno due attributi come chiave e due attributi (gli stessi per facilitarmi lo sviluppo) come attributo...

    il problema è che quando faccio una ricerca, settando prima la coppia da cercare, non mi trova l'oggetto e per di più mi stampa a video quello che scrivo (quando non dovrebbe scrivere nulla)...

    ecco la classe classmappa.java che definisce il tipo di oggetti che inserisco nella mappa
    codice:
    public class classmappa {
    
    	private int state;
    	private String message;
    	
    	public void setState ( int state ){
    		this.state = state;
    	}
    	
    	public int getState() {
    		return this.state;
    	}
    	
    	public void setMessage (String message) {
    		this.message = message;
    	}
    	
    	public String getMessage() {
    		return this.message;
    	}
    	
    }
    ed ecco la classe provamappa.java che utilizza classmappa come tipo per gli oggetti della mappa
    codice:
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.*;
    
    public class provamappa {
            static Map mappa = new HashMap();
    	private static String[] alfa = { "zero", "uno", "due" };
    	private static int i;
    	static classmappa i1 = new classmappa();
    	static classmappa i2 = new classmappa();
    	
    	public static void main(String[] args) {
    		String input = null;
    		
    		// popolo la mappa
    		for (i=0; i<3; i++) {
    			i1.setState(i);
    			i1.setMessage(alfa[i]);
    			mappa.put(i1, i1);	// inserisco nella mappa la chiave e il valore 
                                                              // appena settati
    			
    			i2 = (classmappa) mappa.get(i1);
    			System.out.println(i2.getState()+ " "+i2.getMessage());
                            // qui stampa a schermo quanto appena inserito, output corretto!!
    		}
    		
    		// visualizzazione con input da tastiera: mi stampa quello che scrivo
    		BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
    		for (i=0; i<3; i++) {
    			try {
    				i1.setMessage((String) stdIn.readLine());
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    			i1.setState(i);
    
    			if (mappa.containsKey(i1))   // controllo se esiste una chiave 
                            {                                         
    				i2 = (classmappa) mappa.get(i1);
    				System.out.println(i2.getMessage());
    			}
                    }
           }
    }
    il "gioco" sarebbe inserire una stringa da tastiera e se stringa AND intero coincidono con la chiave allora mi stampa a schermo il valore, mentre se non contiene la chiave non deve stampare nulla....considerando anche che l'intero è sempre fornito dal ciclo for...
    invece, come già detto, il containsKey restituisce sempre true, anche se da tastiera scrivo "sette", e mi restituisce quello che scrivo (e non l'oggetto della mappa)....

    un grazie a tutti quelli che mi daranno una mano, è un bel po che ci sto sbattendo la testa
    ∇•E=ρ/ε ; ∇•B=0 ; ∇xE=-∂B/∂t ; ∇xB=μJ+με∂E/∂t....e ho detto tutto!
    Nessun sistema è sicuro se c'è un idiota a gestirlo!
    Coltiva Linux che Windows si pianta da solo!

  2. #2
    Utente di HTML.it
    Registrato dal
    Apr 2007
    Messaggi
    906
    Scusa ma...
    codice:
    public static void main(String[] args) {
    		//...Insersci, bla bla bla, anche se non capisco il ciclo for.
                    //Situazione attuale:hai inserito 1 oggetto nella mappa e il reference i1 punta 
    		//ancora a quell'oggetto
    
    		// visualizzazione con input da tastiera: mi stampa quello che scrivo
    		BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
    		for (i=0; i<3; i++) {
    			try {
                                    //setti il messaggio dell'oggetto della mappa alla stringa 
                                    //appena letta in quanto i1 punta ancora all'oggetto.
    				i1.setMessage((String) stdIn.readLine());
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    			i1.setState(i);
    
    			if (mappa.containsKey(i1))   
                            //E certo che lo contiene c'e' solo quello
                            //Il messaggio naturalmente e' quello che hai scritto da tastiera
                            //perche' sopra l'hai sovrascritto. Quindi la stampa e' corretta
                            {                                         
    				i2 = (classmappa) mappa.get(i1);
    				System.out.println(i2.getMessage());
    			}
                    }
           }
    Secondo me il codice fa quello che hai scritto di fare, il problema e' che quello che hai scritto non e' cio' che vuoi fare. Prova a risistemarlo.

  3. #3
    Utente di HTML.it
    Registrato dal
    Nov 2003
    Messaggi
    178
    ma attraverso il
    mappa.put(i1,i1)
    non aggiungo alla mappa gli oggetti?
    se si allora non mi interessa più sapere dei riferimenti (tanto che li riuso)...

    per quel tuo commento "//setti il messaggio dell'oggetto della mappa alla stringa
    //appena letta in quanto i1 punta ancora all'oggetto."
    mi chiedo come posso modificare la stringa in questo modo visto che comunque è un attributo privato della classe classmappa ed è accessibile solo con i metodi get/set che ho fatto...


    grazie comunque per la risposta
    ∇•E=ρ/ε ; ∇•B=0 ; ∇xE=-∂B/∂t ; ∇xB=μJ+με∂E/∂t....e ho detto tutto!
    Nessun sistema è sicuro se c'è un idiota a gestirlo!
    Coltiva Linux che Windows si pianta da solo!

  4. #4
    Utente di HTML.it
    Registrato dal
    Apr 2007
    Messaggi
    906
    ma attraverso il mappa.put(i1,i1) non aggiungo alla mappa gli oggetti?
    se si allora non mi interessa più sapere dei riferimenti (tanto che li riuso)...
    Si, aggiungi l'oggetto, ma se non ne istanzi uno nuovo ogni volta, vai a modificare quello che hai inserito nella mappa, alla fine la mappa avra' una sola entry.

    Ti faccio vedere. Prima di tutto per snellire il codice metto un costruttore a classmappa.
    La parte in fondo alla classe e' invece fondamentale quando si vuole usare una propria classe come chiave di un HashMap.
    codice:
    public class classmappa {
            private int state;
    	private String message;
    
            public classmappa(int state, String message){
                    this.state = state;
    		this.message = message;
            }
    	
    	public void setState ( int state ){
    		this.state = state;
    	}
    	public int getState() {
    		return this.state;
    	}
    	public void setMessage (String message) {
    		this.message = message;
    	}
    	public String getMessage() {
    		return this.message;
    	}
            //Sovrascrivo questo metodo perche' Map lo usa per il confronto tra key e 
            //generalmente 2 istanze diverse di un oggetto restituiscono false anche se gli oggetti
            //contengono gli stessi valori.
            public boolean equals(Object obj) {
                classmappa a = (classmappa)obj;
                return (a.getState()==this.getState()&&a.getMessage().equals(this.getMessage()));
            }
            
            //Sovrascrivo questo oggetto perche' il codice hash e' usato dalle hashmap per 
            //indicizzare le chiavi e 2 istanze diverse di un oggetto hanno hashCode diversi
            //anche se gli oggetti contengono gli stessi valori.
            public int hashCode() {
                String tmp = state+message;
                return tmp.hashCode();
            }
            
    }
    Il costruttore puoi anche non metterlo, ma almeno usi una riga sola invece di chiamare i due metodi set.
    Nell'altra classe
    codice:
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.*;
    
    public class provamappa {
            static Map mappa = new HashMap();
    	private static String[] alpha = {"zero", "uno", "due"};
    	private static int i;
    	static classmappa i1;
    	
    	public static void main(String[] args) {
    		String input = null;
    		
    		// popolo la mappa
    		for (i=0; i<3; i++) {
                            i1 = new classmappa(i, alpha[i]); 
                            //Con la new istanzio un nuovo oggetto ogni volta
    			mappa.put(i1, i1);	// inserisco nella mappa la chiave e il valore 
                                                              // appena settati
    			System.out.println(i1.getState()+ " "+i1.getMessage());
                            // qui stampa a schermo quanto appena inserito, output corretto!!
    		}
    		
    		// visualizzazione con input da tastiera: mi stampa quello che scrivo
    		BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
    		for (i=0; i<3; i++) {
    			try {
                                    i1 = new classmappa(i, stdIn.readLine());
    				//Anche stavolta istanzio un nuovo oggetto,
    				//altrimenti andrei a modificare quello nella map.
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    
    			if (mappa.containsKey(i1))  {                                         
    				System.out.println("Messaggio: "+i1.getMessage());
    			} else {                                        
    				System.out.println("Oggetto non presente");
    			}
                    }
           }
    }
    Spero di aver chiarito i tuoi dubbi, ciao.

  5. #5
    Utente di HTML.it
    Registrato dal
    Nov 2003
    Messaggi
    178
    ah ora ho capito....
    nel mio caso creavo un solo oggetto e lo modificavo di volta in volta, mentre ora crea tanti oggetti i1 (eliminando il vecchio ad una nuova new perché non ha riferimenti) diversi tra loro....

    grazie, proverò questa soluzione e vedo se funziona anche nell'altro progetto (più grande) che usa sempre le mappe


    ps
    non sapevo ci fosse bisogno dell'override dei metodi equals e hashCode
    ∇•E=ρ/ε ; ∇•B=0 ; ∇xE=-∂B/∂t ; ∇xB=μJ+με∂E/∂t....e ho detto tutto!
    Nessun sistema è sicuro se c'è un idiota a gestirlo!
    Coltiva Linux che Windows si pianta da solo!

  6. #6
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da Le0n
    non sapevo ci fosse bisogno dell'override dei metodi equals e hashCode
    Sono fondamentali, specialmente nelle collezioni di tipo Map.

    Comunque i metodi scritti da simo7784 non sono il massimo ... specialmente equals.

    Ecco una soluzione migliore e più corretta:
    codice:
    public boolean equals (Object obj) {
        if (this == obj)
            return true;
        if (!(obj instanceof classmappa))
            return false;
        classmappa o = (classmappa) obj;
        return (o.getState() == this.getState() && o.getMessage().equals(this.getMessage()));
    }
    
    public int hashCode () {
        return getState () ^ getMessage().hashCode ();
    }
    Per equals() è sbagliato fare subito un cast
    classmappa a = (classmappa)obj;

    Se il cast fallisce a runtime, viene lanciata l'eccezione ClassCastException e questo non è il comportamento corretto per equals. In questa situazione deve ritornare false e basta.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  7. #7
    Utente di HTML.it
    Registrato dal
    Apr 2007
    Messaggi
    906
    E' ovvio, era solo per spiegare... :P
    I metodi poi se li scrive come preferisce usando XOR,concatenamenti o quello che piu' gli aggrada. Era solo per spiegargli come mai non il test non gli andava e per dirgli che doveva sovrascrivere quei due metodi se voleva usare una classe come chiave...

  8. #8
    Utente di HTML.it
    Registrato dal
    Nov 2003
    Messaggi
    178
    grazie ad entrambi, mi avete chiarito un problema che m'assillava da tempo!!!

    ultima domanda in merito:
    ma i metodi equals e hashCode sono chiamati quando vado a fare la containsKey?
    cioè containsKey chiama equals che usa hashCode?
    ∇•E=ρ/ε ; ∇•B=0 ; ∇xE=-∂B/∂t ; ∇xB=μJ+με∂E/∂t....e ho detto tutto!
    Nessun sistema è sicuro se c'è un idiota a gestirlo!
    Coltiva Linux che Windows si pianta da solo!

  9. #9
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da Le0n
    ultima domanda in merito:
    ma i metodi equals e hashCode sono chiamati quando vado a fare la containsKey?
    cioè containsKey chiama equals che usa hashCode?
    containsKey() fa una cosa di questo tipo: calcola il hash code della chiave passata in input (quindi chiama hashCode() sul reference passato come argomento), tramite questo hash code determina quale è il "bucket" da utilizzare, quindi scansiona la lista di entry che fanno capo a quel bucket e di ogni entry prende la chiave e la compara con equals() alla chiave passata in input fino a quando trova la stessa chiave.

    Questo ovviamente a grandi linee ... se vuoi i dettagli, leggi il sorgente della classe HashMap ad esempio.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  10. #10
    Utente di HTML.it
    Registrato dal
    Nov 2003
    Messaggi
    178
    Originariamente inviato da andbin
    containsKey() fa una cosa di questo tipo: calcola il hash code della chiave passata in input (quindi chiama hashCode() sul reference passato come argomento), tramite questo hash code determina quale è il "bucket" da utilizzare, quindi scansiona la lista di entry che fanno capo a quel bucket e di ogni entry prende la chiave e la compara con equals() alla chiave passata in input fino a quando trova la stessa chiave.

    Questo ovviamente a grandi linee ... se vuoi i dettagli, leggi il sorgente della classe HashMap ad esempio.
    grazie, sei stato molto chiaro
    ora capisco il perché bisogna scrivere i metodi hashCode e equals

    per "bucket" cosa intendi?
    l'insieme degli oggetti che hanno lo stesso hashcode ??
    ∇•E=ρ/ε ; ∇•B=0 ; ∇xE=-∂B/∂t ; ∇xB=μJ+με∂E/∂t....e ho detto tutto!
    Nessun sistema è sicuro se c'è un idiota a gestirlo!
    Coltiva Linux che Windows si pianta da solo!

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.