Java – i metodi equals e hashCode e un esempio di override

Siamo alla base, direi, ma a volte i programmatori sono persone insensibili, non fanno la raccolta differenziata, non aiutano le vecchiette ad attraversare la strada e si dimenticano alcune cose basilari sui metodi equals() e hashCode(), che si ereditano dalla classe Object, e di cui a volte è necessario fare l’override. E visto che lo si fa, tanto vale farlo bene.

Entrambi sono definiti nella documentazione ufficiale di java.

Il metodo equals()

Indica se due oggetti sono uguali. Avete definito una classe, avete due oggetti istanze di quella classe, dovete decidere quali sono le condizioni per qui questi oggetti devono considerarsi uguali.

Questo metodo applica una relazione di equivalenza che:

  • E’ riflessiva: per ogni x non nullo, x.equals(x) deve restituire true.
  • E’ simmetrica: per ogni x e y non nulli, x.equals(y) deve restituire true se e solo se y.equals(x) restituisce true.
  • E’ transitiva: per ogni x, y e z non nulli, se x.equals(y) retituisce true e y.equals(z) restituisce true, allora x.equals(z) deve restituire true.
  • E’ consistente: per ogni x e y non nulli, se nessuna delle informazioni utilizzate per calcolare l’uguaglianza viene modificata, chiamate multiple a x.equals(y) devono restituire coerentemente o sempre true, o sempre false.
  • Per ogni istanza di x non nulla, x.equals(null) deve restituire false

Nel caso della classe Object, x.equals(y) equivale a (x==y) cioè sono uguali se e solo se puntano allo stesso oggetto.

Il metodo hashCode()

Restituisce un valore hash per un oggetto. E’ usato in tanti ambiti, per esempio nelle hashmap.

Le sue peculiarità sono:

  • Una volta istanziato l’oggetto, il valore restituito da questo metodo deve essere consistente (non deve cambiare) se non cambiano i campi con cui viene calcolato.
  • Istanze dello stesso oggetto su diverse esecuzioni dell’applicazioni devono invece restituire valori diversi.
  • Se due oggetti sono dichiarati uguali dal metodo equals() allora la funzione hash deve restituire lo stesso valore.

Non è obbligatorio che due oggetti dichiarati diversi dal metodo equals() abbiano un hash code diverso, ma è comunque consigliato, per questioni di performance.

Un esempio

Utilizzo Eclipse per generare entrambi i metodi. Parto da un POJO definito in questo modo:

public class Libro {
 
	private String isbn;
 
	private String autore;
 
	public String getIsbn() {
		return isbn;
	}
 
	public void setIsbn(String isbn) {
		this.isbn = isbn;
	}
 
	public String getAutore() {
		return autore;
	}
 
	public void setAutore(String autore) {
		this.autore = autore;
	}
}

L’unica cosa che si deve fare è decidere quali saranno i campi che dovranno essere usati sia per l’equals() che per l’hashCode(). In questo esempio è il campo isbn.
A questo punto è sufficiente:

  • Scegliere il menu contestuale source->Generate hashCode() and equals()
    Java – i metodi equals e hashCode e un esempio di override
    Java – i metodi equals e hashCode e un esempio di override -Eclipse 1
  • Scegliere i campi da utilizzare
    Java – i metodi equals e hashCode e un esempio di override 2
    Java – i metodi equals e hashCode e un esempio di override – Eclipse 2

Il risultato è questo:

@Override
public int hashCode() {
	final int prime = 31;
	int result = 1;
	result = prime * result + ((isbn == null) ? 0 : isbn.hashCode());
	return result;
}
 
@Override
public boolean equals(Object obj) {
	if (this == obj)
		return true;
	if (obj == null)
		return false;
	if (getClass() != obj.getClass())
		return false;
	Libro other = (Libro) obj;
	if (isbn == null) {
		if (other.isbn != null)
			return false;
	} else if (!isbn.equals(other.isbn))
		return false;
	return true;
}

Ora per esempio il seguente codice

Libro libro1 = new Libro();
libro1.setIsbn("123456789");
libro1.setAutore("Pippo");
 
Libro libro2 = new Libro();
libro2.setIsbn("123456789");
libro2.setAutore("Pluto");
 
System.out.println(libro1.equals(libro2));

restituisce true

Conclusioni

  • Se una classe esegue l’override del metodo equals, deve farlo anche del metodo hashCode
  • I metodi equals() e hashCode() devono usare lo stesso set di campi
  • Se due oggetti sono uguali, deve essere uguale anche il loro hash code

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>