Problema classe astratta e metodo equals

di il
14 risposte

Problema classe astratta e metodo equals

Ciao a tutti, vi posto le classi e poi vi spiego il problema:
package graph;

public abstract class Vertex {
	
	/**
	 * The label of this vertex
	 */
	private final String label;
	
	/**
	 * Constructs a vertex with the given label.
	 *  
	 * @param label
	 */
	public Vertex(String label) {
		this.label = label;
	}
	
	/**
	 * Returns the label of this vertex.
	 * 
	 * @return a String which is the label of this vertex.
	 */
	public String getLabel() {
		return this.label;
	}
	
	/**
	 * Returns a string representation of this vertex. 
	 * HINT: potrebbe essere la label stessa.
	 * 
	 * @return a string representation of this vertex
	 */
	@Override
    public abstract String toString();
	
	/**
	 * Returns the graph this vertex belongs to
	 * 
	 * @return the graph this vertex belongs to
	 */
	public abstract Graph getGraph();
	
	/**
	 * Compares this vertex to the specified object. The result is true if and only if 
	 * the argument is not null and is a Vertex object with the same label.
	 * 
	 * @param o The object to compare this Vertex against
	 * 
	 * @return true if the given object represents a vertex with the same label of this vertex, false otherwise
	 */
	@Override
	public boolean equals(Object o) {
		return (o != null) && (o instanceof Vertex) && ((Vertex) o).getLabel() == this.getLabel(); 
	}


}
package impl;

import graph.Graph;
import graph.Vertex;

public class VertexImpl extends Vertex{
	public String label;
	public Graph grafo;
	public String colour;
	public double livello;
	public double endTime;
	public double startTime;

	
	public VertexImpl(String label, Graph grafo, String colour, double livello) {
		super(label);
		this.grafo = grafo;
		this.colour = colour;
		this.livello = livello;
	}


	@Override
	public String toString() {
		return null;
	}


	@Override
	public Graph getGraph() {
		return this.grafo;
	}


	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((label == null) ? 0 : label.hashCode());
		return result;
	}
}
Poi ho una classe(DirectedGraphAdjListImpl) in cui inizializzo un HashMap<Vertex, LinkedList<Vertex>> in questo modo:
public DirectedGraphAdjListImpl(int numVertices) {
		adj = new HashMap<Vertex, LinkedList<Vertex>>();
		for(int i=1; i <= numVertices; i++) {
			Vertex v = new VertexImpl(Integer.toString(i), this, DEFAULT_VERTEX_COLOUR, Double.POSITIVE_INFINITY);
			adj.put(v, new LinkedList<Vertex>());
		}
	}
Il problema è il seguente:
Se io provo a fare:
Set<Vertex> set = new HashSet<Vertex>;
set = adj.keySet(); //dove adj è il nome della mia hashmap

Se io stampo questo set, mi crea il giusto numero di chiavi all'interno di set, ma tutte con valore null.
Il fatto è che se invece di fare il procedimento precedente faccio:
for(Vertex v : adj.keySet()){
System.out.println(v);
}
In questo caso mi stampa tranquillamente tutti i vertici, ovvero le chiavi. Non riesco proprio a capire perchè il primo metodo mi da quel problema, che dopotutto è uguale al for successivo. Inoltre i metodi containsKey sembrano non funzionare.
Credo ci sia un problema di tipo degli oggetti da qualche parte. Il metodo equals mi è stato dato così, quindi non è li il problema.
Sapete aiutarmi? Grazie mille

14 Risposte

  • Re: Problema classe astratta e metodo equals

    Giuso ha scritto:


    Il metodo equals mi è stato dato così, quindi non è li il problema.
    Sapete aiutarmi?
    La classe Vertex è "quasi" corretta. Ma viene usato == per confrontare le due label:

    return (o != null) && (o instanceof Vertex) && ((Vertex) o).getLabel() == this.getLabel();

    Questo è semplicemente sbagliato in generale (e se è stato messo per un qualche motivo, andrebbe chiarito). Per il resto è ok.

    Mentre invece in VertexImpl non va molto bene:
    - i campi come public, non è granché (viola l'incapsulamento)
    - il campo label poi non serve a nulla, dato che Vertex lo ha già!
    - il hashCode() usa label ma è il label specifico di VertexImpl (che nel codice di VertexImpl NON viene assegnato, dovresti assegnarlo tu esternamente essendo public).

    Quindi:
    - sistemare il livello di accesso dei campi (con dei getter/setter appositi)
    - usare nel hashCode il getLabel() di Vertex
  • Re: Problema classe astratta e metodo equals

    Ok, ho modificato HashCode() in questo modo:
    @Override
    	public int hashCode() {
    		final int prime = 31;
    		int result = 1;
    		result = prime * result + ((getLabel() == null) ? 0 : getLabel().hashCode());
    		return result;
    	}
    Ho tolto il campo label in VertexImpl perchè effettivamente non serviva. Per la visibilità posso mettere i campi come privati?
    public class VertexImpl extends Vertex{
    	public Graph grafo;
    	public String colour;
    	public double livello;
    	public double endTime;
    	public double startTime;
    
    	
    	public VertexImpl(String label, Graph grafo, String colour, double livello) {
    		super(label);
    		this.grafo = grafo;
    		this.colour = colour;
    		this.livello = livello;
    	}
    Con metodi getter e setter intendi inserire dei semplici getColore, getLabel ecc all'interno di VertexImpl?
    Il costruttore penso sia ok. Ho provato a stampare il contenuto dei campi, mi stampa correttamente colour e livello, ma il campo label rimane settato a null, come mai? Come se il costruttore chiamato con super non facesse il "suo dovere".

    Aggiorno messaggio: Il campo label me lo stampa facendo la getLabel(), ma se io stampo soltanto Vertex v perchè ho come output null?
  • Re: Problema classe astratta e metodo equals

    Giuso ha scritto:


    Ok, ho modificato HashCode() in questo modo:
    Ok

    Giuso ha scritto:


    Per la visibilità posso mettere i campi come privati?
    Sì, è bene private.

    Giuso ha scritto:


    Con metodi getter e setter intendi inserire dei semplici getColore, getLabel ecc all'interno di VertexImpl?

    getLabel no, è già in Vertex.

    Giuso ha scritto:


    Il costruttore penso sia ok.
    Il costruttore deve ricevere label di certo. Più tutti gli altri dati (e non necessariamente tutti) che ritieni utili già alla costruzione dell'oggetto.

    Giuso ha scritto:


    Il campo label me lo stampa facendo la getLabel(), ma se io stampo soltanto Vertex v perchè ho come output null?
    Devi ridefinire il toString() in modo utile per descrivere l'oggetto.

    Ribadisco la questione del == nel equals.
  • Re: Problema classe astratta e metodo equals

    Ah giusto scusami, la questione dell'equals l'avevo dimenticata. Ora se quel metodo sia implementato bene oppure no non lo so, ma non posso in alcun modo modificarlo (è un esercizio per un esame universitario) e pertanto devo farmelo andar bene (Anche perchè al prof penso funzioni in quel modo).
    Quello che posso fare è prendere il tuo consiglio e riferirglielo.

    La questione del Vertex null non riguarda solo la stampa(infatti ora ho implementato il toString() in modo che mi restituisce solo il label). Come dicevo a inizio discussione, anche facendo una semplice adj.containsKey(v) dove v è un Vertex passato al metodo, questo v ha valore null, pertanto tutti i metodi inerenti all'hashmap (come la get ecc) non mi funzionano perchè vedono un oggetto null (nonostante la stampa mi dice che l'oggetto ha i campi settati nel modo giusto). Sai dirmi il perchè?

    PS: i campi colore, livello, time... li uso in altre classi pertanto mi servono siano public. L'unico private può essere "grafo".
  • Re: Problema classe astratta e metodo equals

    Giuso ha scritto:


    ma non posso in alcun modo modificarlo (è un esercizio per un esame universitario) e pertanto devo farmelo andar bene (Anche perchè al prof penso funzioni in quel modo).
    Ma potresti lecitamente ridefinirlo in VertexImpl

    Giuso ha scritto:


    Quello che posso fare è prendere il tuo consiglio e riferirglielo.
    E comunque se rimane quel == in equals vuol dire che due VertexImpl sono "uguali" solo se hanno lo STESSO oggetto String in label. Quindi dipenderebbe da come gestisci/crei le stringhe e PUÒ essere un problema!

    Giuso ha scritto:


    anche facendo una semplice adj.containsKey(v) dove v è un Vertex passato al metodo, questo v ha valore null
    Se v è null hai una variabile non inizializzata (o messa esplicitamente a null) ... è un'altra questione.

    Giuso ha scritto:


    PS: i campi colore, livello, time... li uso in altre classi pertanto mi servono siano public. L'unico private può essere "grafo".
    Infatti i getter/setter public ok. I campi NOO.
  • Re: Problema classe astratta e metodo equals

    È proprio quello che si vuole, cioè identificare un Vertice unicamente con il campo label, effettivamente non lo avevo specificato. Quindi ora può sembrare corretto equals?

    Le stringhe le inserisco io nel main con Input.read e le passo alla new VertexImpl.

    Ho provato a togliere le variabili che non inizializzavo nel costruttore ma comunque quando chiamo i metodi dell'hash, i vertici li vede nulli...
  • Re: Problema classe astratta e metodo equals

    Giuso ha scritto:


    è proprio quello che si vuole, cioè identificare un Vertice unicamente con il campo label
    No, NON è quello il punto!!

    Giuso ha scritto:


    Le stringhe le inserisco io nel main con Input.read e le passo alla new VertexImpl.
    Visto che chiedi proprio in input le stringhe, se ad esempio chiedi all'utente 2 label (per andare poi a creare 2 VertexImpl) e l'utente scrive la stessa stringa, i due oggetti String sono DISTINTI, perché creati a runtime.
    Quindi i due oggetti VertexImpl NON saranno mai uguali, anche se entrambi hanno delle label con la stessa sequenza di caratteri.

    Ti è chiaro o no? Queste sono le "basi" di Java.
  • Re: Problema classe astratta e metodo equals

    È quello che pensavo, ma se io faccio v1.label.equals(v2.label) e i label sono stati inseriti da me con la stessa sequenza di caratteri(ma in realtà oggetti distinti) questo mi restituisce true. Perché allora se le stringhe le vede uguali gli oggetti (che sono uguali se è uguale il label) non lo sono?
  • Re: Problema classe astratta e metodo equals

    Giuso ha scritto:


    ma se io faccio v1.label.equals(v2.label)
    Con getLabel() ovviamente, volendo fare questo confronto.
    Ma comunque NON è questo che ti serve.

    Giuso ha scritto:


    Perché allora se le stringhe le vede uguali gli oggetti (che sono uguali se è uguale il label) non lo sono?
    Perché HashMap, per le chiavi, usa quel equals di Vertex che sta usando == per confrontare le label.
    Quindi con due label di uguale contenuto ma come oggetti String DISTINTI, per HashMap i due oggetti VertexImpl sono due chiavi DIVERSE.
  • Re: Problema classe astratta e metodo equals

    Ok, ho rifatto il metodo equals in modo corretto, ora funziona.
    Avrei bisogno di ordinare una LinkedList secondo un suo campo. Qual è il modo più rapido? Ho provato con comparable ma non ho capito come usare il metodo sort.
  • Re: Problema classe astratta e metodo equals

    Giuso ha scritto:


    Ho provato con comparable ma non ho capito come usare il metodo sort.
    Ne ho parlato tante volte sul forum. Es. qui
  • Re: Problema classe astratta e metodo equals

    Ok sono riuscito.
    Ti chiedo un'altra cosa. Se un metodo mi restituisce un Collection<Collection<Vertex>>, potresti darmi un esempio di che tipo di oggetto potrei creare? Perchè ad esempio una linkedList di LinkedList non me la fa restituire. Ho provato varie combinazioni di collezioni ma mi da errori.
  • Re: Problema classe astratta e metodo equals

    Giuso ha scritto:


    Se un metodo mi restituisce un Collection<Collection<Vertex>>
    Sicuro che ti serve una struttura così articolata?

    Giuso ha scritto:


    potresti darmi un esempio di che tipo di oggetto potrei creare? Perchè ad esempio una linkedList di LinkedList non me la fa restituire. Ho provato varie combinazioni di collezioni ma mi da errori.
    Nota che NON puoi creare un LinkedList<LinkedList<Vertex>> per restituirlo come Collection<Collection<Vertex>>. Questo perché i generics sono "invarianti" (vedi giusto questa discussione dell'altro ieri).

    Perché è vero che LinkedList è sottotipo di Collection ma un LinkedList<LinkedList<XYZ>> NON è un sottotipo di Collection<Collection<XYZ>>

    Devi PRIMA creare un LinkedList<Collection<Vertex>> ovvero
    LinkedList<Collection<Vertex>> listaPrincipale = new LinkedList<Collection<Vertex>>();
    POI per ciascuna sottolista:
    LinkedList<Vertex> listaVertexN = new LinkedList<Vertex>();
    // .... listaVertexN.add( .... );
    listaPrincipale.add(listaVertexN);
    ecc....

    alla fine: return listaPrincipale;


    P.S. giusto per chiarire: LinkedList<Collection<Vertex>> È un sottotipo di Collection<Collection<Vertex>>
  • Re: Problema classe astratta e metodo equals

    Mi serve quella struttura per ottenere le componenti fortemente connesse, che sono appunto liste di vertici. Quindi in out avrò una lista contenente liste di vertici. Comunque ho fatto come mi hai detto. Grazie
Devi accedere o registrarti per scrivere nel forum
14 risposte