Java 컬렉션 – hashCode() 및 equals() – Java에서 equals() 및 hashcode() 메서드를 재정의하는 방법은 무엇입니까?
게시 됨: 2018-08-08
Java의 equals()
및 hashCode()
는 Object 클래스와 일부 또는 핵심 Java 라이브러리에서 선언되는 두 가지 기본 메소드입니다.
Java에서 아래 문제 중 하나가 있는 경우 올바른 위치에 있습니다.
- Java 실습 -> 같음 구현
- override – Java에서 equals 및 hashCode 재정의
- Java에서 equals() 메소드를 재정의하는 방법
- Java에서 hashCode() 메서드를 재정의하는 방법
- Java에서 equals 및 hashCode 메소드를 재정의하는 방법
- Java에서 equals 메소드를 재정의하는 방법과 이유
- equals()를 재정의하는 경우 왜 항상 hashcode()를 재정의합니까?
첫 번째 Reference Equality
및 Logical Equality
를 이해하기 위해 간단한 예를 살펴보겠습니다. 같음 연산자(==)는 두 문자열의 참조(메모리 주소)를 두 개의 다른 숫자로 비교합니다. 이를 Reference equality
이라고 합니다.
Logical equality
은 참조 값 대신 개체의 데이터를 비교합니다.
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 ) ) ; } } |
산출:
1 2 3 4 5 6 7 8 9 |
Reference Equality Result : false false true Logical Equality Result : true false true |
hashCode 와 equals 는 밀접하게 관련되어 있습니다.
- equals 를 재정의하는 경우 hashCode 를 재정의해야 합니다.
- hashCode 는 동일한 개체에 대해 동일한 값을 생성해야 합니다.
- equals 및 hashCode 는
same set of significant fields
의존해야 합니다. 이 두 가지 방법 모두에서 동일한 필드 집합을 사용해야 합니다. 모든 필드를 사용할 필요는 없습니다. 예를 들어, 다른 것에 의존하는 계산된 필드는equals
및hashCode
에서 생략될 가능성이 매우 높습니다.
equals 를 구현할 때 필드는 유형에 따라 다르게 비교됩니다.
- 컬렉션을 포함한 개체 필드: equals 사용
- type-safe 열거형: equals 또는 == 를 사용합니다(이 경우 동일한 값입니다)
- null 가능성이 있는 개체 필드: == 와 equals 를 모두 사용
- 배열 필드:
Arrays.equals
사용 - float 또는 double 이외의 기본 필드: == 사용
-
float
: 다음을 사용하여 int 로 변환Float.floatToIntBits ,
를 사용하고 == -
double
:Double.doubleToLongBits
를 사용하여 long 으로 변환한 다음 == 사용
해시 코드 구현:
- 클래스가 equals 를 재정의하면 hashCode 를 재정의해야 합니다.
- 둘 다 재정의되면 equals 및 hashCode 는 동일한 필드 세트를 사용해야 합니다.
- 두 객체가 같으면 hashCode 값도 같아야 합니다.
- 객체가 변경할 수 없는 경우 hashCode 는 캐싱 및 지연 초기화의 후보입니다.
hashCode 가 개체에 대한 고유 식별자를 제공한다는 것은 널리 알려진 오해입니다. 그렇지 않습니다.
일반 계약에 따라 Java의 equals()
메서드는 반사적, 대칭적, 전이적, 일관성이 있어야 하며 null이 아닌 참조는 false를 반환해야 합니다. 즉, b, c의 임의 값에 대해 다음 테스트를 항상 통과해야 합니다.
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 ) ) ; |
모범 사례를 위해 아래 단계를 사용하여 equals() 메서드를 구현하십시오.
- this == that을 사용하여 참조 평등을 확인하십시오.
-
instanceof
를 사용하여 올바른 인수 유형 테스트 - 인수를 올바른 유형으로 캐스팅하십시오.
- 평등에 대한 중요한 필드 비교
다음은 완전한 예입니다.
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 ; } } |
Eclipse 콘솔 출력:
1 2 |
Test1 : One and Two are equal Test2 : Three and Four are not equal |