hashCode() verändert sich

pg1337

Bekanntes Mitglied
Morgen,

habe ne Frage bezüglich der hashcode() - Methode.

Hier n kleines Programm:

Java:
public class MainHash {
	
	public static void main(String[] args) {

		Person p1= new Person("Schind", "Phil", 18);
		Person p2= new Person("Schind", "Phil", 18);
		
		p1=p2;
		
		System.out.println(p1.hashCode());
		System.out.println(p2.hashCode());		
	}
}

Java:
public class Person {
	
	String name, vorname;
	int alter;
	
	public Person(String name, String vorname, int alter){
		this.name= name;
		this.vorname=vorname;
		this.alter=alter;
		
	}
}


in der main rufe ich den hashcode() auf, dieser verändert sich jedoch beim 4en - 5en mal Ausführen des Programms:



Ausgabe 1:

714682869
714682869

Ausgabe 2:

798941612
798941612



Woran liegt das?
greetz
 
Erklär mal, was du in Zeile 8 von MainHash machst...

Darüber hinaus solltest du vielleicht für Person die hashCode() Methode überschreiben.
 
Deine Person-Klasse implementiert die hashCode()-Methode nicht. In dem Fall gilt die Default-Implementierung von java.lang.Object, und die gibt einen nicht näher spezifizierten Wert zurück, der von Session zu Session unterschiedlich sein kann.
 
Jetzt überschreibt die Klasse Person hashcode, kommen immernoch gleiche Ergebnisse.
Hab diese Methode noch nicht oft aufgerufen, also net böse sein wenn ich da was falsch mache jetzt nur am Rande mal benutzt 😛

Java:
	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		return super.hashCode();
	}
}
 
Die Membervariablen sollten schon mit in die Berechnung des HashCodes eingehen, ungefähr so:

Java:
public class Person {

	String name, vorname;
	int alter;
	
	public Person(String name, String vorname, int alter){
		this.name= name;
		this.vorname=vorname;
		this.alter=alter;
		
	}

  public int hashCode(){
    return alter + (vorname!=null?vorname.hashCode()*37:0) + (name!=null?name.hashCode()*31:0);
  }
}

Aber jede vernünftige IDE kann dir da automatisch eine hashCode-Methode generieren.
 
Wenn man hashCode() implementiert, sollte man auch equals() entsprechend implementieren.
In Eclipse geht das z.B. automatisch mit "Source->generate hashCode() and equals()".
 

Leider fehlen mir auf obiger Seite die zwei wichtigsten Regeln zwischen equals() und hashCode():

1. falls x.equals(y) == true, dann muss auch x.hashCode()==y.hashCode() true liefern
2. falls x.hashCode()!=y.hashCode() true, dann muss auch x.equals(y) == false sein!

Zudem gilt, dass equals() mindestens die gleichen Attribute wie hashCode() berücksichtigen muss, es dürfen aber auch mehr sein.
 
2. falls x.hashCode()!=y.hashCode() true, dann muss auch x.equals(y) == false sein!
Das ist laut Kontrakt keine MUSS-Anforderung, sondern nur eine SOLLTE-Anforderung. Es ist aber auf jeden Fall SEHR ratsam, sich daran zu halten.
 
Das ist laut Kontrakt keine MUSS-Anforderung, sondern nur eine SOLLTE-Anforderung. Es ist aber auf jeden Fall SEHR ratsam, sich daran zu halten.
Irrtum... das ist lt. Kontrakt sehrwohl ein muss, ist nämlich der Umkehrschluss zu erstens. Was aber dagegen auch noch geht: [c](x.hashCode() == y.hashCode()) != x.equals(y)[/c] und das ist im Kontrakt das KANN.
 
Was aber dagegen auch noch geht: [c](x.hashCode() == y.hashCode()) != x.equals(y)[/c] und das ist im Kontrakt das KANN.

Das ist aber auch klar, wenn man sich überlegt, dass man mehr Objekte hat, als es verschiedene ints gibt. Dann muss es zwangsläufig irgendwie zu Kollisionen kommen. Oder alle möglichen Long-Werte als String-Repräsentation, und von diesen String hashCode() aufrufen, da gibt es auch Kollisionen. (Meist aber leider schon früher 😉)
 
Das ist laut Kontrakt keine MUSS-Anforderung, sondern nur eine SOLLTE-Anforderung. Es ist aber auf jeden Fall SEHR ratsam, sich daran zu halten.

Für mich bedeutet ein "required" ein MUSS, damit auch dir Logik von equals() und hashCode() auf die verwendeten Collection zutrifft. Die erste Regel besagt nichts anderes, dass zwei gleiche Objekte den gleichen hashCode() haben müssen, ansonsten ist der hashCode() fehlerhaft. Umgekehrt besagt die zweite Regel, dass der hashCode() von zwei ungleichen Objekten ebenfalls ungleich sein muss! Wenn man diese zwei Regel auf z.B. einen HashSet anwendet, sind sie einleuchtend.

Zur Vollständigkeit noch die "Not Required (But Allowed)" Kontraktpunkte:
1. Wenn x.hashCode() == y.hashCode(), dann sollte auch x.equals(y) == true zutreffen, muss aber nicht.
2. Wenn x.equals(y) == false, dann gibt es keine Anforderungen an den hashCode()
 
Umgekehrt besagt die zweite Regel, dass der hashCode() von zwei ungleichen Objekten ebenfalls ungleich sein muss!
Nein, andersrum! Wenn die Hashcodes verschieden sind, sind die Objekte ungleich. Ungleiche Objekte können aber trotzdem gleiche Hashcodes haben.
 

Zurück
Oben