Java

[Java]hashCode와 equals 메서드

DevStory 2022. 9. 4.

hashCode와 eqausl 메서드

이번 포스팅은 java의 최상위 클래스인 Object 클래스의 hashCode() 메서드와 equals() 메서드에 대해 소개합니다.

 

hashCode() 메서드와 equals() 메서드에 대한 자세한 내용은 아래 포스팅에서 확인할 수 있습니다.

 

[Java]Object 클래스의 hashCode 메서드

Object 클래스의 hashCode 메서드 Java에서 사용되는 해시 코드(Hashcode)는 객체를 식별하기 위한 ID입니다. Java의 모든 객체는 JVM에 의해 고유 번호가 생성되며, 이 고유 번호가 해시 코드입니다. 해시

developer-talk.tistory.com

 

[Java]Object 클래스의 equals 메서드

Object 클래스의 equals 메서드 Java에 모든 클래스는 최상위 클래스인 Object에서 파생됩니다. 따라서, Object 클래스에 구현된 메서드를 사용할 수 있으며, 그중 equals() 메서드를 사용하여 두 객체가 동

developer-talk.tistory.com


hashCode와 equals 메서드의 계약관계

hashCode() 메서드와 equals() 메서드 사이에는 한 가지 계약관계가 존재합니다. 두 객체를 equals() 메서드로 비교했을 때, true를 반환하면 hashCode() 메서드도 true를 반환해야 합니다.

 

Object 클래스의 equals() 메서드와 hashCode() 메서드는 위 계약관계를 따릅니다. 따라서, eqausl() 메서드를 재정의할 때마다 위 계약조건을 충족하도록 hashCode() 메서드를 재정의해야 합니다.

 

아래 사진에서 확인할 수 있듯이 IntelliJ는 생성자, 프로퍼티, toString() 메서드 등 메서드를 자동으로 생성하거나 재정의하는 기능을 제공합니다. equals() 메서드만 자동으로 재정의하거나 반대로 hashCode() 메서드만 재정의하는 기능은 제공하지 않습니다.

 

"equals() and hashCode()"라는 문구에서 알 수 있듯이 eqausl() 메서드와 hashCode() 메서드 둘 다 재정의하는 것을 권장합니다.

위 계약관계를 따르지 않는다고 에러가 발생하는 것은 아니지만, equals() 메서드만 재정의하거나 반대로 hashCode() 메서드만 재정의하는 것은 좋은 소스 코드가 아닙니다.

 

equals() 메서드는 주로 클래스에 존재하는 필드의 값을 비교하기 위해 재정의됩니다. 그렇다면, hashCode() 메서드도 해당 필드를 기반으로 해시 코드를 생성하도록 재정의되어야 합니다.

 

다음 예제는 IntelliJ에서 제공하는 기능을 사용하여 Person 클래스의 Name 필드를 비교하고 Name 필드를 기반으로 해시 코드를 생성하도록 equals() 메서드와 hashCode() 메서드를 재정의합니다.

public class Person {
  private String Name;
  private Integer Age;

  public Person(String name, Integer age) {
    Name = name;
    Age = age;
  }

  public String getName() {
    return Name;
  }

  public void setName(String name) {
    Name = name;
  }

  public Integer getAge() {
    return Age;
  }

  public void setAge(Integer age) {
    Age = age;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Person person = (Person) o;
    return Objects.equals(Name, person.Name);
  }

  @Override
  public int hashCode() {
    return Objects.hash(Name);
  }
}

 

다음 예제는 Name 필드의 값은 동일하지만, Age 필드의 값이 Person 타입인 두 개의 객체를 생성 후 equals() 메서드와 hashCode() 메서드를 호출합니다.

public static void main(String args[]) {
  Person person1 = new Person("둘리", 20);
  Person person2 = new Person("둘리", 50);

  System.out.println("equals(): " + person1.equals(person2));
  System.out.println("person1.hashCode(): " + person1.hashCode());
  System.out.println("person2.hashCode(): " + person2.hashCode());
}

[실행 결과]

equals(): true
person1.hashCode(): 1478771
person2.hashCode(): 1478771

재정의된 equals() 메서드는 Name 필드의 값을 비교하므로 true를 반환하고 재정의된 hashCode() 메서드도 Name 필드의 값을 기반으로 해시 코드를 생성하므로 동일한 해시 코드를 출력합니다.

 

이번에는 Name 필드의 값이 다른 Person 타입인 두 개의 객체를 생성 후 equals() 메서드와 hashCode() 메서드를 호출합니다.

public static void main(String args[]) {
  Person person1 = new Person("둘리", 20);
  Person person2 = new Person("또치", 50);

  System.out.println("equals(): " + person1.equals(person2));
  System.out.println("person1.hashCode(): " + person1.hashCode());
  System.out.println("person2.hashCode(): " + person2.hashCode());
}

[실행 결과]

equals(): false
person1.hashCode(): 1478771
person2.hashCode(): 1497703

Name 필드의 값이 다르므로 재정의된 equals() 메서드는 false를 반환하고 재정의된 hashCode() 메서드는 서로 다른 해시 코드를 반환합니다.


hashCode 메서드와 equals 메서드의 관계

  • equals() 메서드가 true를 반환하는 경우 hashCode() 메서드는 true를 반환합니다.
  • equals() 메서드가 false를 반환하는 경우 hashCode() 메서드는 true 또는 false를 반환합니다.
  • hashCode() 메서드가 true를 반환하는 경우 equals() 메서드는 true 또는 false를 반환합니다.
  • hashCode() 메서드가 false를 반환하는 경우 equals() 메서드는 false를 반환합니다.
반응형

댓글