Colecții Java – hashCode() și equals() – Cum să suprascrieți metoda equals() și hashcode() în Java?
Publicat: 2018-08-08
equals()
și hashCode()
în Java sunt două metode fundamentale care sunt declarate în clasa Object și biblioteca Java parțială sau de bază.
Dacă aveți una dintre preocupările de mai jos în Java, atunci sunteți în locul potrivit.
- Practici Java -> Implementarea equals
- override – Suprascrierea equals și hashCode în Java
- Cum să suprascrieți metoda equals() în java
- Cum să suprascrieți metoda hashCode() în java
- Cum să suprascrieți metoda equals și hashCode în Java
- Cum și de ce să suprascrieți metoda equals în Java
- De ce să înlocuiți întotdeauna hashcode() dacă suprascrierea este egală cu ()?
Să aruncăm o privire la un exemplu simplu pentru a înțelege mai întâi egalitatea de Reference Equality
Logical Equality
. Operatorul de egalitate (==) compară referințele (adresele din memorie) ale celor două șiruri de caractere ca două numere diferite - aceasta este cunoscută sub numele de Reference equality
.
Logical equality
compară datele obiectelor în loc de valoarea referințelor.
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 ) ) ; } } |
Ieșire:
1 2 3 4 5 6 7 8 9 |
Reference Equality Result : false false true Logical Equality Result : true false true |
hashCode și equals sunt strâns legate:
- dacă suprascrieți equals , trebuie să înlocuiți hashCode .
- hashCode trebuie să genereze valori egale pentru obiecte egale.
- equals și hashCode trebuie să depindă de
same set of significant fields
. Trebuie să utilizați același set de câmpuri în ambele metode. Nu ești obligat să folosești toate câmpurile. De exemplu, un câmp calculat care depinde de alții ar trebui foarte probabil să fie omis dinequals
șihashCode
.
La implementarea equals , câmpurile sunt comparate diferit, în funcție de tipul lor:
- câmpuri obiect, inclusiv colecții: folosește equals
- enumerări de tip sigur: utilizați fie equals , fie == (în acest caz, ele echivalează cu același lucru)
- câmpuri obiect posibil-null: utilizați atât == cât și equals
- câmpuri matrice: utilizați
Arrays.equals
- câmpuri primitive, altele decât float sau double : utilizați ==
-
float
: convertiți în int folosindFloat.floatToIntBits ,
apoi utilizați == -
double
: convertiți în long folosindDouble.doubleToLongBits
, apoi utilizați ==
Implementarea hashCode :
- dacă o clasă suprascrie equals , trebuie să suprascrie hashCode
- când ambele sunt suprascrise, equals și hashCode trebuie să utilizeze același set de câmpuri
- dacă două obiecte sunt egale, atunci și valorile lor hashCode trebuie să fie egale
- dacă obiectul este imuabil, atunci hashCode este un candidat pentru cache și inițializare leneșă
Este o concepție greșită populară că hashCode oferă un identificator unic pentru un obiect. Aceasta nu.
Prin contract general, metoda equals()
în Java trebuie să fie reflexivă, simetrică, tranzitivă, consecventă și orice referință non-nulă trebuie să returneze false. Cu alte cuvinte, pentru valorile arbitrare ale a, b și c, următoarele teste trebuie întotdeauna să treacă:
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 ) ) ; |
Pentru cea mai bună practică, utilizați pașii de mai jos pentru a implementa metoda equals():
- Utilizați acest == aceea pentru a verifica egalitatea referințelor
- Utilizați
instanceof
pentru a testa tipul corect de argument - Transmite argumentul la tipul corect
- Comparați domenii semnificative pentru egalitate
Iată un exemplu complet.
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 ; } } |
Ieșire consola Eclipse:
1 2 |
Test1 : One and Two are equal Test2 : Three and Four are not equal |