자바

equals() / hashCode()

2022. 8. 10. 20:16
목차
  1. equals 재정의
  2. equals 규약
  3. 상속(inheritance)보다는 합성(composition)
  4. hashCode() 재정의 이유

그림판 작품

class Person {
    private String name;
    private int age;
    
    public Person() { }
    public Person(String name, int age) {
    	this.name = name;
        this.age = age;
    }
}

Person p1 = new Person("justin", 10);
Person p2 = new Person("justin", 10);

boolean samePerson = p1.equals(p2);	// ?

s1.equals(s2) 는 true일 것 같지만 false이다.

그 이유는 Object 클래스의 equals함수는 단지 == 비교로 두 객체의 메모리 주소를 비교하고 있기 때문이다.

new Person() 명령어를 통해 메모리에 2개의 객체를 생성했고 p1, p2는 각기 다른 주소를 가리키고 있는 것이다.

equals 재정의

@Override
public boolean equals(Object o) {
	if (o == this)
    	return true;
 	if (!(o instanceof Student))
    	return false;
    Student other = (Student)o;
    boolean nameIsEqual = (this.name == null && other.name == null) ||
    	(this.name != null && this.name.equals(other.name));
    return this.age == other.age && nameIsEqual;
}

equals 규약

  • 재귀: 객체는 자신과 같아야 한다.
  • 대칭: x.equals(y)는 y.equals(x)와 동일한 결과를 반환해야 한다.
  • 전이: x.equals(y) 및 y.equals(z)이면 x.equals(z)도 참이여야한다.
  • 일관성: equals()에 포함된 속성이 변경되는 경우에만 equals()의 값이 변경되어야 한다.

equals 규약 위반 - equals()를 재정의한 클래스를 상속하는 경우 가장 자주 발생한다.

class Student extends Person {
    private String major;
    
    @Override
    public boolean equals(Object o) {
    	if(o == this)
        	return true;
        if(!(o instanceof Student))
        	return false;
        Student other = (Studnet)o;
        boolean nameIsEqual = (this.name == null && other.name == null) ||
        	(this.name != null && this.name.equals(other.name));
        boolean majorIsEqual = (this.major == null && other.major == null) ||
        	(this.major != null && this.major.equals(other.major));
        return this.age == this.age && nameIsEqual && majorIsEqual;
    }
}
    
Person p1 = new Person("Amy", 20);
Student s1 = new Student("Amy", 20, "Design");

p1.equals(s1);	// true
s1.equals(p1);	// false
equals의 대칭 규약 위반이 일어난다.

상속(inheritance)보다는 합성(composition)

class Teacher {
    private Person person;
    private String major;
    
    Person(String name, int age, String major) {
    	this.person = new Person(name, age);
        this.major = major;
    }
    
    @Override
    public boolean equals(Object o) {
    	if(o == this)
        	return true;
        if(!(o instanceof Teacher)
        	return false;
        Teacher other = (Teacher)o;
        boolean personIsEqual = (this.person == null && other.person) ||
        	(this.person != null && this.person.equals(other.person));
        boolean majorIsEqual = (this.major == null && other.major) ||
        	(this.major != null && this.major.equals(other.major));
        return personIsEqual && majorIsEqual;
    }
}

hashCode() 재정의 이유

hash 값을 사용하는 Collection(HashSet, HashMap, HashTable)을 사용할 때 문제가 발생한다. 이러한 Collection은 hashCode()를 사용하여 주어진 키에 대한 해시 값을 계산하기 때문이다.

hashCode ()규약

  • 내부 일관성: hashCode() 값은 equals() 안에 있는 속성이 변경되는 경우에만 변경될 수 있다. 동일한 객체는 수정되지 않는 한 hashCode()는 일관되게 동일한 값을 반환해야 한다.
  • equals()에 따라 두 객체가 같으면 두 객체의 각각 hashCode() 또한 동일한 값이 생성되어야 한다.
  • equals()에 따라 두 객체가 같지 않더라도 두 객체의 각각 hashCode()는 같을 수 있다.
class Person {
    private String name;
    private int age;
    
    public Person() { }
    public Person(String name, int age) {
    	this.name = name;
        this.age = age;
    }
    
    @Override
    public int hashCode() {
    	return age * name.hashCode();
    }
}

표준 hashCode() 구현

@Override
public int hashCode() {
    int hash = 7;
    hash = 31 * hash + age;
    hash = 31 * hash + (name == null ? 0 : name.hashCode());
    return hash;
}

Java 7부터는 Objects.hash() 메서드를 제공

Lombok을 사용하여 @EqualsAndHashCode 어노테이션 사용 가능

 

참고 https://www.baeldung.com

  1. equals 재정의
  2. equals 규약
  3. 상속(inheritance)보다는 합성(composition)
  4. hashCode() 재정의 이유
'자바' 카테고리의 다른 글
  • try-with-resources
  • SOLID 원칙
  • Immutable String - Java String Pool
  • Java Virtual Machine (JVM)
규동
규동
규동
규동노트
규동
전체
오늘
어제
  • 분류 전체보기 (32)
    • 스프링 (8)
    • 자바 (5)
    • 웹 (3)
    • 코딩테스트 (1)
    • 데이터베이스 (1)
    • 인프라 (1)
    • 기록 (5)
    • 개발서적 (7)
    • 앱 (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • TDD
  • 국제화
  • d-day 구하기
  • 디자인 패턴
  • JUnit
  • 다국어
  • 클린코드
  • Cleancode
  • 외부설정

최근 댓글

최근 글

hELLO · Designed By 정상우.
규동
equals() / hashCode()
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.