equals() & hashCode()

.·2022년 7월 29일
0

Computer Science

목록 보기
54/81

Object class

package java.lang;

public class Object {
    public boolean equals(Object obj) {
        return (this == obj);
    }

    @IntrinsicCandidate
    public native int hashCode();
}

모든 Java 객체의 조상 객체인 Object 클래스에 equals()와 hashCode()가 정의되어 있고, 이를 상속받는다.

equals()

특징

Identity vs Equality - equals() 참고

Object Class

조상 객체 Object의 equals()는 두 객체가 동일한지 확인하는 메서드이지만

Override

Object를 상속받은 자식 클래스들 중 String, Integer 등에서 동등성 비교를 하게 오버라이드하였다.

예시

  1. equals() override 전

equals()를 재정의하지 않은 객체를 사용했다. 두 employee 인스턴스는 id가 같아서 동일한 사람으로 처리하고 싶지만 false를 반환한다.

public class EqualsTest {
    public static void main(String[] args) {
        Employee employee1 = new Employee();
        Employee employee2 = new Employee();
 
        employee1.setId(1);
        employee2.setId(1);
 
        System.out.println(employee1.equals(employee2));  //false
    }
}
  1. equals() override 후

이를 해결하기 위해 Employee 클래스에서 equals()를 오버라이드해준다.

@Getter
@Setter
public class Employee {
    private int id;
    private String name;

    @Override
    public boolean equals(Object o) {
        if (o == null) {
            return false;
        }
        if (o == this) {
            return true;
        }
        if (getClass() != o.getClass()) {
            return false;
        }

        Employee e = (Employee) o;
        return (this.getId() == e.getId());
    }
}

hashCode()

특징

  • 객체에 대한 해시 코드 값을 반환한다.
  • 자바 어플리케이션이 실행되는 동안(runtime) 같은 객체에 대해 항상 같은(유일한) integer 값을 반환한다.
  • HashTable, HashSet, HashMap 등의 자료구조를 데이터가 저장되는 위치를 결정하기 위해 사용한다.

Object Class

  • heap에 저장된 객체의 메모리 주소 반환 (항상 그런 것은 아님)
  • native → Java Native Interface(JNI)의 native code를 사용해 구현되었음
    • 자바가 아닌 언어로 구현된 부분을 자바에서 이용하고자 할 때 사용한다.
    • 일반 개발자가 사용할 수는 없다.

Override

  1. equals() override 후 & hashCode() override 전

Object의 hashCode()는 객체 메모리 주소값을 반환하기 때문에 employee1과 employee2는 다른 해시값을 가지고, HashSet에서도 각자 다른 위치에 저장된다.

public class EqualsTest {
    public static void main(String[] args) {
        Employee employee1 = new Employee();
        Employee employee2 = new Employee();
 
        employee1.setId(1);
        employee2.setId(1);

        System.out.println(employee1.equals(employee2));  // true
 
        Set<Employee> employees = new HashSet<Employee>();
        employees.add(employee1);
        employees.add(employee2);
         
        System.out.println(employees);  // 2개 객체 출력
    }
}
  1. equals() override 전 & hashCode() override 후

같은 아이디를 가지면

@Getter
@Setter
public class Employee {
    private int id;
    private String name;

    @Override
    public boolean equals(Object o) {...}

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + getId();
        return result;
    }
}

관계

동일한 객체 = 동일한 메모리 주소 = 동일한 해시코드
equlas()를 오버라이드한다면 hashCode()도 오버라이드 되어야 한다.

  1. 자바 프로그램을 실행하는 동안 equals()에 사용된 정보가 수정되지 않았다면, hashCode()는 항상 동일한 정수값을 반환해야 한다.
    • 프로그램을 실행할 때마다 달라지는 것은 상관 없다.
  2. equals()에 의해 두 객체가 동일함을 알게되면, hashCode() 메서드를 호출할 때 두 객체가 반드시 동일한 integer 결과값을 만들도록 해야한다.
  3. equals()에 의해 두 객체가 동일하지 않다면, hashCode()가 다른 값을 반환해도 된다. (not required)
    • 하지만 동일하지 않은 객체들이 다른 정수값을 만드는 것이 hash table의 성능을 향상시킬 수도(may) 있다.

가이드라인

  1. hashCode()equals()를 생성하기 위해서는 같은 attribute를 이용한다.
  2. equals()는 일관되어야 한다. 객체가 수정되지 않았다면 항상 결과가 동일해야 한다.
  3. a.equlas(b) == true이면 a.hashCode() == b.hashCode() 도 true여야 한다.
  4. equals()hashCode()는 항상 함께 override 되어야 한다.

출처

0개의 댓글