hashCode()
와equals()
가 무엇인가요?- map에서 객체를 키로 사용하면 어떻게 되나요?
==
과equals()
의 차이는 무엇인가요?
면접에서 value와 reference 에 대해서 많은 질문을 받았다.
객체는 참조형이다! 왜 오브젝트가 중요한 지 다시금 되새겼다.
equals() 메서드는 Object 클래스에서 상속받는다.
이때 equals()는 두 객체가 같은 메모리 주소를 가리키고 있는지를 확인해서 동등성을 비교한다.
결국 value 가 같아도 참조값이 다르다면 다르다고 반환한다.
그치만 우리는 대부분 value가 같다면 같은 객체라고 보고 싶을 수 있지요?
따라서 equals()를 재정의한다.
따라서 우리가 equals()
를 재정의해서 두 객체가 동일합니다~
라고 판단할 때는 반드시 같은 해시코드를 반환하도록 해야 한다.
해시 기반의 컬렉션들(HashMap, HashSet ...)에서 정상적으로 동작하지 않을 수 있다.
결론적으로 equals()를 재정의할 때에는 hashCode()도 함께 재정의해야 한다.
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Person person = (Person) obj;
return age == person.age && Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
public static void main(String[] args) {
Person p1 = new Person("aa", 10);
Person p2 = new Person("aa", 10);
System.out.println(p1.equals(p2)); // true
System.out.println(p1.hashCode()); // 97195
System.out.println(p2.hashCode()); // 97195
}
두 값은 동등하다고 true를 출력하겠지만, 둘의 해시코드는 달라진다.
이러면 위에서 말했듯 해시를 구현할 때 정확한 값 비교가 안될 수가 있다.
key-value 로 구성된 자료구조. 고유한 키 값을 가진다.
해시 기반의 컬렉션을 사용할 때 객체를 키로 사용하게 되면 객체의 hashCode()와 equals() 메소드의 구현에 따라 맵의 동작이 크게 달라질 수 있다.
그렇다면 고유해야하는 이 키 값이 객체일 경우 어떤 경우를 고유하다고 판단하는가?
동등하다고 판단되면 =
equals()
가true
를 반환하면,
Map에서 같은 키로 간주한다.
위와 같은 Person 객체가 있을 때,
public static void main(String[] args) {
Map<Person, String> map = new HashMap<>();
map.put(new Person("John", 30), "Developer");
System.out.println(map.get(new Person("John", 30))); // Developer
}
새로운 객체를 만들어서 참조값이 다르다고 해도, hashCode가 같아지도록 재정의했기 때문에 결과는 Developer라고 출력하게 된다.
Object의 동등성과 관련된 hashCode()와 equals()에 대해 말씀드리겠습니다.
equals()는 객체의 동등성을 비교하는 메서드로, 기본적으로는 객체 주소값이 동일해야 true를 반환합니다.
hashCode()는 java에서 해시 컬렉션에서 객체를 저장하거나 검색할 때 해시코드를 사용하는데, 이 때의 해시코드를 반환하는 메서드입니다.
값이 같은 경우는 같은 객체라고 보고 싶다면, equals()를 재정의를 해줍니다. 이 때 hashCode()도 같이 재정의를 해주어서 같은 해시코드를 반환하도록 해야합니다. 이를 어기면 해시 컬렉션을 사용할 때 제대로 된 결과값이 나오지 않을 수 있습니다.
Map에서의 키는 동등한 객체일 때, 즉 equals()가 true로 반환되면 같은 키라고 여깁니다. 따라서 적절하게 재정의를 해주어야 합니다.
연산자
==
은 참조값이 같으면 같은 객체라고 판단합니다. 따라서 기본타입을 비교할 때 사용하는 것을 권장합니다. 객체를 비교할 때에는 equals() 를 사용하여 정확한 동등성을 비교할 수 있도록 합니다.
equals()와 hashCode()를 재정의할 때 고려해야 할 사항은 무엇인가요?
hashCode() 메소드를 재정의하는 경우, 어떤 기준으로 해시코드를 생성하는 것이 좋을까요?
Objects.hash()
를 통해 알아서 생성해준다.equals() 메소드를 재정의할 때 instanceof 대신 getClass()를 사용하는 이유는 무엇인가요?
*Pitty는 나의 GPT 프롬프트의 애칭이다.