toString()
재정의를 하지 않았을 때 @해시코드
라고 알고 있었는데 System.identityHashCode()
를 사용했을 때 나오는 숫자와 달랐다.
차이가 무엇일까?
public class Main {
public static void main(String[] args) {
int[] str6 = {1,2,3,4,5,6};
System.out.println("==============================");
System.out.println(str6);
System.out.println(System.identityHashCode(str6));
System.out.println(str6.hashCode());
System.out.println("==============================");
}
}
==============================
[I@776ec8df
2003749087
2003749087
==============================
해쉬코드
2003749087
를 16진수로 변환한 값이@776ec8df
이다.
그렇다면 hashcode()
와 메모리 주소는 같은 것일까?
@IntrinsicCandidate
public native int hashCode();
개체의 해시 코드 값을 반환합니다.
이 메서드는 java.util.HashMap에서 제공하는 것과
같은 해시 테이블의 이점을 위해 지원됩니다.
hashCode의 일반 계약은 다음과 같습니다:
자바 응용 프로그램을 실행하는 동안
동일한 객체에 대해 두 번 이상 호출될 때마다,
객체에 대한 동등한 비교에 사용되는 정보가 수정되지 않는다면
hashCode 메서드는 동일한 정수를 일관성 있게 반환해야 합니다.
이 정수는 응용 프로그램의 한 실행에서 동일한 응용 프로그램의
다른 실행으로 일관성을 유지할 필요는 없습니다.
동일한 방법에 따라 두 개체가 동일한 경우 두 개체 각각에 대해
hashCode 메서드를 호출하면 동일한 정수 결과가 생성되어야 합니다.
동일한 방법에 따라 두 개체가 동일하지 않은 경우 두 개체 각각에 대해 해시 코드 메서드를 호출하면 서로 다른 정수 결과가 생성될 필요는 없습니다. 그러나 프로그래머는 동일하지 않은 개체에 대해 서로 다른 정수 결과를 생성하면 해시 테이블의 성능이 향상될 수 있음을 알아야 합니다.
반환:
이 개체의 해시 코드 값입니다.
구현 요구사항:
class Object에 의해 정의된 hashCode 메서드는 합리적으로 실용적인 경우 고유한 개체에 대해 고유한 정수를 반환합니다.
참고 항목:
equals(오브젝트), System.identityHashCode
hashCode는 단순히 고유한 개체에 고유한 정수를 반환을 하지, 메모리주소로 무조건 구현되지는 않는다
hashcode()
, equals()
재정의package ex03;
import lombok.*;
import java.util.Objects;
@AllArgsConstructor
@NoArgsConstructor
public class Animal {
private String name;
private String type;
private String cry;
}
package ex03;
public class AnimalMain {
public static void main(String[] args) {
Animal animal = new Animal("야옹이", "포유류", "야옹");
Animal animal1 = new Animal("야옹이", "포유류", "야옹");
System.out.println(animal.hashCode());
System.out.println(animal1.hashCode());
System.out.println(animal.equals(animal1));
}
}
1324119927
990368553
false
두 객체는 다른 해쉬값을 갖고, 다른 객체라고 판단한다. 하지만 두 객체는 갖고 있는 데이터가 동일하다. 이 때, 같은 객체라고 판단하기 위해서는
hashcode()
와equals()
의 재정의가 필요하다
package ex03;
import lombok.*;
import java.util.Objects;
@AllArgsConstructor
@NoArgsConstructor
public class Animal {
private String name;
private String type;
private String cry;.
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Animal animal = (Animal) o;
return Objects.equals(name, animal.name) && Objects.equals(type, animal.type) && Objects.equals(cry, animal.cry);
}
}
1324119927
990368553
true
true
값이 나왔다. 하지만 해쉬값은 다르게 나온다. 이 때, 같은 데이터면 같은 해쉬값을 호출하도록 해쉬코드를 재정의 하자
package ex03;
import lombok.*;
import java.util.Objects;
@AllArgsConstructor
@NoArgsConstructor
public class Animal {
private String name;
private String type;
private String cry;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Animal animal = (Animal) o;
return Objects.equals(name, animal.name) && Objects.equals(type, animal.type) && Objects.equals(cry, animal.cry);
}
@Override
public int hashCode() {
return Objects.hash(name, type, cry);
}
}
-1620938993
-1620938993
true
해쉬값도 동일하게 출력된다
❓ 그렇다면 왜 해쉬코드 까지 같이 재정의 해야하는 걸까? 같은 객체임을 확인하기만 하면 된다면 equals()
만 재정의하면 되지 않을까?
다시, 해쉬코드를 재정의하지 않고 equal()
만 재정의한 상태로 돌아가보자
package ex03;
import java.util.HashSet;
import java.util.Set;
public class AnimalMain {
public static void main(String[] args) {
Animal animal = new Animal("야옹이", "포유류", "야옹");
Animal animal1 = new Animal("야옹이", "포유류", "야옹");
System.out.println(animal.hashCode());
System.out.println(animal1.hashCode());
System.out.println(animal.equals(animal1));
Set<Animal> animals = new HashSet<>();
animals.add(animal);
animals.add(animal1);
System.out.println(animals); // 2개가 나옴
System.out.println(animals.size()); // 2
}
}
1324119927
990368553
true
[ex03.Animal@4eec7777, ex03.Animal@3b07d329]
2
두 객체는 같다고 판단했지만, 중복을 허용하지 않는
set
으로 받았을 때HashSet
은hash
값으로 객체를 판단하므로 두 객체가 다른 객체라고 판단, 둘 다 저장하게 된다.
-1620938993
-1620938993
true
[ex03.Animal@9f626f0f]
1
같은 객체라고 판단하고, 1개만 추가된다.
동등객체, 둘 중 하나라도 다르면 다른 객체라고 판단한다.
참고 : https://tecoble.techcourse.co.kr/post/2020-07-29-equals-and-hashCode/
https://hye0-log.tistory.com/48