Java-Sammlungen – hashCode() und equals() – Wie kann man die equals()- und hashcode()-Methode in Java überschreiben?
Veröffentlicht: 2018-08-08
equals()
und hashCode()
in Java sind zwei grundlegende Methoden, die in der Object-Klasse und einem Teil oder einer Kern-Java-Bibliothek deklariert werden.
Wenn Sie eines der folgenden Probleme in Java haben, sind Sie hier richtig.
- Java-Praktiken -> Implementieren von equals
- override – Überschreiben von equals und hashCode in Java
- So überschreiben Sie die Methode equals () in Java
- So überschreiben Sie die Methode hashCode () in Java
- So überschreiben Sie die Methode equals und hashCode in Java
- Wie und warum die equals-Methode in Java überschrieben wird
- Warum hashcode() immer überschreiben, wenn equals() überschrieben wird?
Werfen wir einen Blick auf ein einfaches Beispiel, um zunächst die Reference Equality
und die Logical Equality
zu verstehen. Der Gleichheitsoperator (==) vergleicht die Referenzen (Adressen im Speicher) der beiden Strings als zwei verschiedene Zahlen – dies wird als Reference equality
bezeichnet.
Die Logical equality
vergleicht die Daten der Objekte anstelle des Wertes der Referenzen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
package com . crunchify . tutorials ; /** * @author Crunchify.com */ public class CrunchifyLogicalVsReferenceEqality { public static void main ( String [ ] args ) { String strA = new String ( "eBay" ) ; String strB = new String ( "eBay" ) ; String strC = new String ( "Paypal" ) ; // Create a String reference and assign an existing String's reference to it // so that both references point to the same String object in memory. String strD = strA ; // Print out the results of various equality checks // Reference Equality System . out . println ( "Reference Equality Result:" ) ; System . out . println ( strA == strB ) ; System . out . println ( strA == strC ) ; System . out . println ( strA == strD ) ; // Logical Equality System . out . println ( "\nLogical Equality Result:" ) ; System . out . println ( strA . equals ( strB ) ) ; System . out . println ( strA . equals ( strC ) ) ; System . out . println ( strA . equals ( strD ) ) ; } } |
Ausgabe:
1 2 3 4 5 6 7 8 9 |
Reference Equality Result : false false true Logical Equality Result : true false true |
hashCode und equals sind eng verwandt:
- Wenn Sie equals überschreiben, müssen Sie hashCode überschreiben.
- hashCode muss gleiche Werte für gleiche Objekte generieren.
- equals und hashCode müssen von
same set of significant fields
abhängen. Sie müssen bei beiden Methoden denselben Satz von Feldern verwenden. Sie müssen nicht alle Felder verwenden. Beispielsweise sollte ein berechnetes Feld, das von anderen abhängt, sehr wahrscheinlich ausequals
undhashCode
weggelassen werden.
Bei der Implementierung von equals werden Felder je nach Typ unterschiedlich verglichen:
- Objektfelder, einschließlich Sammlungen: verwenden Sie equals
- typsichere Aufzählungen: Verwenden Sie entweder equals oder == (in diesem Fall sind sie gleich)
- möglicherweise-Null-Objektfelder : Verwenden Sie sowohl == als auch gleich
- Array-Felder: Verwenden
Arrays.equals
- primitive Felder außer Float oder Double : verwenden Sie ==
-
float
: Konvertieren in int mitFloat.floatToIntBits ,
verwenden Sie dann == -
double
: mitDouble.doubleToLongBits
in long umwandeln, dann == verwenden
HashCode implementieren:
- Wenn eine Klasse equals überschreibt, muss sie hashCode überschreiben
- Wenn sie beide überschrieben werden, müssen equals und hashCode denselben Satz von Feldern verwenden
- Wenn zwei Objekte gleich sind, müssen ihre hashCode- Werte ebenfalls gleich sein
- Wenn das Objekt unveränderlich ist, ist hashCode ein Kandidat für Caching und Lazy-Initialisierung
Es ist ein weit verbreiteter Irrglaube, dass hashCode eine eindeutige Kennung für ein Objekt bereitstellt. Es tut nicht.
Gemäß allgemeinem Vertrag muss die Methode equals()
in Java reflexiv, symmetrisch, transitiv und konsistent sein, und jede Nicht-Null-Referenz muss falsch zurückgeben. Mit anderen Worten, für beliebige Werte von a, b und c müssen die folgenden Tests immer bestanden werden:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/ reflexive property assertTrue ( a . equals ( a ) ) ; // symmetric property assertTrue ( a . equals ( b ) == b . equals ( a ) ) ; // transitive property if ( a . equals ( b ) && b.equals(c) ) { assertTrue( a.equals(c) ); } // consistency property assertTrue ( a . equals ( b ) == a . equals ( b ) ) ; // non-null property assertFalse ( a . equals ( null ) ) ; |
Verwenden Sie für die Best Practice die folgenden Schritte, um Ihre Methode equals () zu implementieren:
- Verwenden Sie this == that, um die Referenzgleichheit zu überprüfen
- Verwenden Sie
instanceof
, um den richtigen Argumenttyp zu testen - Wandeln Sie das Argument in den richtigen Typ um
- Vergleichen Sie signifikante Felder auf Gleichheit
Hier ist ein vollständiges Beispiel.
CrunchifyImplementEqualsHashCode.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
package crunchify . com . tutorials ; /** * * @author Crunchify.com * How to Override equals() method in Java? * How to Override hasCode() method in Java? * version:1.2 * */ public class CrunchifyImplementEqualsHashCode { public static void main ( String [ ] args ) { CrunchifyImplementEqualsHashCode crunchifyTest = new CrunchifyImplementEqualsHashCode ( ) ; Crunchify one = new Crunchify ( 1 ) ; Crunchify two = new Crunchify ( 1 ) ; crunchifyTest . test1 ( one , two ) ; Crunchify three = new Crunchify ( 1 ) ; Crunchify four = new Crunchify ( 2 ) ; crunchifyTest . test2 ( three , four ) ; } public void test1 ( Crunchify one , Crunchify two ) { if ( one . equals ( two ) ) { System . out . println ( "Test1: One and Two are equal" ) ; } else { System . out . println ( "Test1: One and Two are not equal" ) ; } } public void test2 ( Crunchify three , Crunchify four ) { if ( three . equals ( four ) ) { System . out . println ( "Test2: Three and Four are equal" ) ; } else { System . out . println ( "Test2: Three and Four are not equal" ) ; } } } class Crunchify { private int value ; Crunchify ( int val ) { value = val ; } public int getValue ( ) { return value ; } // The method does override or implement a method declared in a supertype. @Override public boolean equals ( Object o ) { // null check if ( o == null ) { return false ; } // this instance check if ( this == o ) { return true ; } // instanceof Check and actual value check if ( ( o instanceof Crunchify ) && (((Crunchify) o).getValue() == this.value)) { return true; } else { return false ; } } @Override public int hashCode ( ) { int result = 0 ; result = ( int ) ( value / 11 ) ; return result ; } } |
Ausgabe der Eclipse-Konsole:
1 2 |
Test1 : One and Two are equal Test2 : Three and Four are not equal |