class temp {
int id;
public int getId() {
return id;
}
temp(int id) {
this.id = id;
}
public void setId(int id) {
this.id = id;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
temp other = (temp) obj;
if (id != other.id)
return false;
return true;
}
}
public class testClass {
public static void main(String[] args) {
temp t1 = new temp(1);
temp t2 = new temp(1);
System.out.println(t1.equals(t2));
Set<temp> tempList = new HashSet<temp>(2);
tempList.add(t1);
tempList.add(t2);
System.out.println(tempList);
}
Il programma aggiunge entrambi gli elementi al Set. All'inizio sono rimasto scioccato perché, aggiungendo i metodi da impostare, viene invocato il metodo equals.HashSet consente l'inserimento di elementi duplicati se hashCode() non viene sovrascritto
Ma poi ho calpestato il metodo hashCode:
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
return result;
}
E poi non ho aggiunto. Questo è sorprendente poiché il metodo Javadoc di Set e add() dice che controlla solo equals() durante l'aggiunta nel Set.
e questo è il Javadoc per add():
/**
* Adds the specified element to this set if it is not already present.
* More formally, adds the specified element <tt>e</tt> to this set if
* this set contains no element <tt>e2</tt> such that
* <tt>(e==null ? e2==null : e.equals(e2))</tt>.
* If this set already contains the element, the call leaves the set
* unchanged and returns <tt>false</tt>.
*
* @param e element to be added to this set
* @return <tt>true</tt> if this set did not already contain the specified
* element
*/
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
poi ho capito che il HashSet è implementato come un HashMap e nella mappa, la hashCode dell'oggetto viene utilizzato come chiave. Quindi, li sta trattando con chiavi diverse se non si sostituisce hashCode.
Non dovrebbe essere presente nella documentazione del metodo add() o di HashSet?
L'intera ragione per cui esiste la funzione hashCode() è per le raccolte basate su hash. Come dovrebbe una collezione "sapere" quale funzione hash usare se non la si definisce? –
Ho scoperto che il metodo equals() della classe temp non viene mai chiamato in questo caso (provato sysout), quindi la JVM richiama il valore predefinito equals() se non abbiamo hashCode() implementato per soddisfare il contratto di JVM specifica. Interessante !!!!!!! –
Chiama solo 'equals' se i' hashCode() 's sono uguali. Non chiama il valore predefinito uguale se lo si sostituisce. –