public boolean equals(Object obj){
return (this == obj);
}
🔍 여기서...
String을 비교할 때 equals로 비교해야 하는 이유
라는 주제로 정리한 적이 있었다.
== 연산자
와 equals
의 차이를 정리해두었는데, String 클래스는 equals
함수를 재정의하여 메모리 주소 비교가 아닌 문자열 '값'을 비교하기 때문에 equals
를 활용해서 비교할 수 있었던 것이었다.
int hashCode()
로 정의된 hashCode()
는 실행 중(Runtime) 객채의 유일한 integer값을 반환한다.public native int hashCode();
native 키워드는 메소드가 JNI(Java Native Interface)라는 native code를 이용해 구현되었음을 의미한다.
native는 메소드에만 적용 가능한 제어자이며, Java가 아닌 C or C++ 등 언어로 구현된 부분을 JNI를 통해 Java에서 이용하고자 할 때 사용된다. (일반 개발자들은 사용할 수 없다.)
hashCode는 HashTable과 같은 자료구조를 사용할 때 데이터가 저장되는 위치를 결정하기 위해 사용된다.
Person person1 = new Person("hoin");
Person person2 = new Person(new String("hoin"));
Person person3 = person2;
// person2,3의 주소는 같지만, person 1의 주소는 다르다. 따라서 해시코드 값도 person1만 다르다.
System.out.println(person1.hashCode());
System.out.println(person2.hashCode());
System.out.println(person3.hashCode());
Class Person {
String name;
Person(String name) {
this.name = name;
}
@Override
public boolean equals(Object obj) {
Person anotherObj = (Person) obj;
return (this.name.equals(anotherObj.name));
}
}
🔍 equals도 봤으니까... (궁금해짐)
String 클래스에서 equals()를 재정의한 것 처럼 hashCode()를 재정의한 것을 살펴보자.
문자열에서 한 글자씩 가져와서 정수값으로 변경한다. 한 글자를 가져와서 정수와 더하면 해당 글자의 ascii 코드의 값을 사용한다.
31 * i
이 (i<<5) - i
와 같기 때문에 곱셈 대신 비트 이동 및 뺄셈으로 처리하여 성능면에서 좀 더 이득이 있기 때문.결론 : 주소값 기준으로 정수값의 hashCode를 생성하지 않음. 서로 다른 String 객체도 문자열이 같으면 hashCode가 같다. hashCode가 유일한 값이라고 했지만 String에서 중복 가능성이 있는 이유.
Person person1 = new Person();
Person person2 = new Person();
// new를 사용해서 객체 생성을 했으므로 서로 주소가 다를 것이다.
person1.setAge(29);
person2.setAge(29);
System.out.println(person1.equals.(person2)); // 주소값이 다르기 때문에 false
public boolean equals(Object o) {
if(o == null) {
return false;
}
if (o == this) {
return true;
}
if (getClass() != o.getClass()) {
return false;
}
Person p = (Person) o;
return (this.getAge() == p.getAge());
}
하지만 아직 문제가 남아있다. hashCode()
는 해당 메모리 주소값을 반환한다고 했다. 그렇기 때문에 주소값이 다른 person 1과 person2는 다른 해시값을 반환할 것이고 HashSet에 저장하려하면 2개의 객체가 서로 다른 위치에 저장될 것이다.
hashCode 메소드도 함께 오버라이드하여 수정해주어야 한다.
@Override
public int hashCode() {
final int PRIME = 31; // 왜 31인지는 위에서 설명했다!
int result = 1;
result = PRIME * result + getAge();
return result;
}
https://brunch.co.kr/@mystoryg/133
https://jisooo.tistory.com/entry/java-hashcode
https://mangkyu.tistory.com/101