Collections Java - hashCode () et equals () - Comment remplacer les méthodes equals () et hashcode () en Java ?
Publié: 2018-08-08
equals()
et hashCode()
en Java sont deux méthodes fondamentales qui sont déclarées dans la classe Object et la partie ou la bibliothèque Java principale.
Si vous avez l'une des préoccupations ci-dessous en Java, vous êtes au bon endroit.
- Pratiques Java -> Implémentation de equals
- override - Remplacer equals et hashCode en Java
- Comment remplacer la méthode equals () en Java
- Comment remplacer la méthode hashCode () en Java
- Comment remplacer les méthodes equals et hashCode en Java
- Comment et pourquoi remplacer la méthode equals en Java
- Pourquoi toujours remplacer hashcode() si le remplacement est égal à() ?
Examinons un exemple simple pour comprendre d'abord l'égalité de Reference Equality
et Logical Equality
. L'opérateur d'égalité (==) compare les références (adresses en mémoire) des deux chaînes comme deux nombres différents - c'est ce qu'on appelle l' Reference equality
.
Logical equality
compare les données des objets au lieu de la valeur des références.
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 ) ) ; } } |
Sortir:
1 2 3 4 5 6 7 8 9 |
Reference Equality Result : false false true Logical Equality Result : true false true |
hashCode et equals sont étroitement liés :
- si vous remplacez equals , vous devez remplacer hashCode .
- hashCode doit générer des valeurs égales pour des objets égaux.
- equals et hashCode doivent dépendre du
same set of significant fields
. Vous devez utiliser le même ensemble de champs dans ces deux méthodes. Vous n'êtes pas obligé d'utiliser tous les champs. Par exemple, un champ calculé qui dépend d'autres devrait très probablement être omis deequals
ethashCode
.
Lors de l'implémentation de equals , les champs sont comparés différemment, selon leur type :
- champs d'objet, y compris les collections : utilisez égal
- énumérations de type sécurisé : utilisez soit equals soit == (ils reviennent au même, dans ce cas)
- champs d'objet éventuellement nuls : utilisez à la fois == et égal
- champs de tableau : utilisez
Arrays.equals
- champs primitifs autres que float ou double : utilisez ==
-
float
: convertir en int en utilisantFloat.floatToIntBits ,
puis utilisez == -
double
: convertir en long en utilisantDouble.doubleToLongBits
, puis utiliser ==
Implémentation de hashCode :
- si une classe remplace equals , elle doit remplacer hashCode
- lorsqu'ils sont tous les deux remplacés, equals et hashCode doivent utiliser le même ensemble de champs
- si deux objets sont égaux, alors leurs valeurs hashCode doivent également être égales
- si l'objet est immuable, alors hashCode est un candidat pour la mise en cache et l'initialisation paresseuse
C'est une idée fausse très répandue que hashCode fournit un identifiant unique pour un objet. Ce ne est pas.
Par contrat général, la méthode equals()
en Java doit être réflexive, symétrique, transitive, cohérente et toute référence non nulle doit renvoyer false. En d'autres termes, pour des valeurs arbitraires de a, b et c, les tests suivants doivent toujours réussir :
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 ) ) ; |
Pour la meilleure pratique, utilisez les étapes ci-dessous pour implémenter votre méthode equals() :
- Utilisez this == that pour vérifier l'égalité des références
- Utilisez
instanceof
pour tester le type d'argument correct - Transmettez l'argument au type correct
- Comparer les champs significatifs pour l'égalité
Voici un exemple 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 ; } } |
Sortie de la console Eclipse :
1 2 |
Test1 : One and Two are equal Test2 : Three and Four are not equal |