Kolekcje Java – hashCode() i equals() – Jak przesłonić metody equals() i hashcode() w Javie?
Opublikowany: 2018-08-08
equals() i hashCode() w Javie to dwie podstawowe metody, które są zadeklarowane w klasie Object i części lub rdzeniu biblioteki Javy.
Jeśli masz jakiekolwiek z poniższych obaw w Javie, to jesteś we właściwym miejscu.
- Praktyki Java -> Implementacja równa się
- override – Zastępowanie równości i hashCode w Javie
- Jak nadpisać metodę equals() w java
- Jak nadpisać metodę hashCode() w java
- Jak nadpisać metodę równości i hashCode w Javie?
- Jak i dlaczego zastąpić metodę równości w Javie?
- Dlaczego zawsze zastępować hashcode(), jeśli zastępowanie równa się()?
Rzućmy okiem na prosty przykład, aby zrozumieć najpierw Reference Equality i Logical Equality . Operator równości (==) porównuje referencje (adresy w pamięci) dwóch ciągów jako dwie różne liczby — jest to znane jako Reference equality .
Logical equality porównuje dane obiektów zamiast wartości referencji.
|
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 ) ) ; } } |
Wyjście:
|
1 2 3 4 5 6 7 8 9 |
Reference Equality Result : false false true Logical Equality Result : true false true |
hashCode i równorzędne są ściśle powiązane :
- jeśli zastąpisz równa się, musisz zastąpić hashCode .
- hashCode musi generować równe wartości dla równych obiektów.
- equals i hashCode muszą zależeć od tego
same set of significant fields. W obu tych metodach musisz użyć tego samego zestawu pól. Nie musisz używać wszystkich pól. Na przykład pole obliczeniowe, które zależy od innych, powinno najprawdopodobniej zostać pominięte wequalsihashCode.
Podczas implementacji equals pola są porównywane w różny sposób, w zależności od ich typu:
- pola obiektów, w tym kolekcje : use equals
- wyliczenia z bezpiecznym typem : użyj równych lub == (w tym przypadku sprowadzają się do tego samego)
- prawdopodobnie puste pola obiektów : użyj zarówno == , jak i równa się
- pola tablicy : użyj
Arrays.equals - pola pierwotne inne niż float lub double : użyj ==
-
float: przekonwertuj na int za pomocąFloat.floatToIntBits ,a następnie użyj == -
double: przekonwertuj na long używającDouble.doubleToLongBits, a następnie użyj ==
Implementacja hashCode :
- jeśli klasa nadpisuje wartość równa , musi nadpisać hashCode
- gdy oba są nadpisane, equals i hashCode muszą używać tego samego zestawu pól
- jeśli dwa obiekty są równe, to ich wartości hashCode również muszą być równe
- jeśli obiekt jest niezmienny, hashCode jest kandydatem do buforowania i leniwej inicjalizacji
Jest to popularne błędne przekonanie, że hashCode zapewnia unikalny identyfikator obiektu. To nie.
Zgodnie z ogólnym kontraktem metoda equals() w Javie musi być zwrotna, symetryczna, przechodnia, spójna, a każde odwołanie niezerowe musi zwracać wartość fałsz. Innymi słowy, dla dowolnych wartości a, b i c, następujące testy muszą zawsze zaliczyć:
|
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 ) ) ; |
Aby uzyskać najlepsze praktyki, wykonaj poniższe czynności, aby zaimplementować metodę equals():
- Użyj tego == that, aby sprawdzić równość referencji
- Użyj
instanceof, aby przetestować poprawny typ argumentu - Przekształć argument na właściwy typ
- Porównaj znaczące pola pod kątem równości
Oto kompletny przykład.
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 ; } } |
Dane wyjściowe konsoli Eclipse:
|
1 2 |
Test1 : One and Two are equal Test2 : Three and Four are not equal |
