티스토리 뷰

Programming/Java

Equlas & HashCode

Albothyl 2016. 8. 15. 18:49

1. Equlas

 

java의 Data Type은 primitive type (int, long)과 reference type (Integer, Long)이 있다.

 

primitive type은 int, char 등이 있는데 이런 형태의 Data Type은 "==" 연산자로 동일한 데이터인지 비교할 수 있다.

 

하지만 reference type은 java에서의 최상위인 java.lang.Object를 상속하는 모든 class로 primitive type처럼 "==" 연산자로 동일한 데이터인지 비교할 수 없다.

reference type을 "=="로 비교하면 데이터를 비교하는게 아니라 해당 object의 reference가 동일한지를 비교하기 때문이다.

 

그런데 왜 "equals" 설명하는데 뜬금없이 primitive type과 reference type을 말했을까?

 

우리가 개발을 할때 모든것을 primitive type으로만 처리하지 않기 때문이다. 
DTO를 직접 비교해야 하는 경우도 많다. 그렇다면 같은 데이터를 가지고 있는 2개의 DTO를 비교하려면 어떻게 해야할까? 방법은 여러가지다.

 

 

위 예제 처럼 DTO안의 특정 primitive type의 값을 직접 비교한거나, equals 메소드를 오버라이드 하는 방법이 있다. java api에 나와있는 equals 메소드를 구현하기 위한 규약이 있다.

 

1. 입력받은 인자중 1개라도 null 이면 return false

2. 입력받은 인자의 reference값이 같다면 return true

3. A.equalse(B) 와 B.equals(A)은 항상 같다.

4. 같은 class 여야 한다. (상속 포함)

- 상속이 가능한 클래스에서 instanseof만으로 type을 비교하면 대칭성이 깨지기 쉬우므로 지양한다. 때문에 getClass를 사용하여 비교한다.

- EX : if (A.getClass() != B.getClass()) { return false; }

5. 값 비교 로직

 

위 조건을 토대로 equals 메소드를 구현하면 아래와 같다.

 

 

 

2. hashCode

 

추가적으로 hash 메소드로 구현해주는것이 좋다. equals메소드만 구현된 UserDTO를 HashMap이나 HashTable등 hash알고리즘이 적용된 자료구조에서 사용하면 데이터가 같더라도 equals메소드에서 같지 안다고 볼 수 있기 때문이다.

 

그렇다면 왜 hashCode가 적용된 자료구조에서는 equals가 제대로 동작하지 안을까?

 

equals는 두 객제의 내용이 같은지 동등석을 비교하는것이고, hashCode는 두 객체가 같은 객체인지 동일성을 비교하기 때문이다.

 

UserDTO a, UserDTO b //a, b의 데이터는 같은 값이 들어있음.

 

 

왜 map의 size가 2일까? Map은 기본적으로 키값이 같으면 앞에 put한 데이터를 엎어친다. HashMap은 먼저 key값중 같은 hashCode를 가진것이 있는지 비교하고, 같은 hashCode가 있다면 equals 메소드를 호출한다. HashMap에서 key값으로 사용중인 UserDTO는 equals만 구현했으므로 UserDTO a, b의 hashCode값이 틀리다. 때문에 equals메소드는 false를 리턴하고 서로 다른값을 가진 객체로 인식한다.

 

UserDTO에 hashCode를 구현하기 앞서 관련된 규약을 먼저 살펴보자.

1. a.equals(b) 가 true 일때 a와 b의 hashCode도 같아야 한다.

2. a.equals(b) 가 false 일때 hashCode값은 같을수도 다를수도 있다. 하지만 성능을 위해서는 hashCode값이 다른것이 좋다.

3. hashCode값이 같다고 해서 a.equals(b) 가 true 인것은 아니다.

 

최종적으로 구현된 UserDTO는 아래와 같다.

 

 

 

3. 주의점

 

아직 끝나지 않았다.

HashMap, HashSet, HastTable등을 사용할때 위 예제처럼 Object가 key로 사용되고 있다면 key로 사용되는 객체나 필드값은 Immutable 있어야 한다. 아래 예제처럼 HashMap에 서로 다른 객체를 put 한뒤에 1개의 객체의 값을 다른 객체와 동일하게 변경해도 HashMap은 put할 시점의 hashCode만을 기억하기 때문에 같은 값이더라도 다르게 인식할 수 있기 때문이다.

 

 

 

 

4. 결론

 

마지막으로 위에처럼 사용할바에야.. 그냥 Lombok을 쓰자..

@EqualsAndHashCode 이 어노테이션 붙여주면 위에 내용 자동으로 만들어준다.

다만 위 어노테이션이 위 예제코드와 같은 동작을 한다는것을 알아야 한다.

 

'Programming > Java' 카테고리의 다른 글

Java Memory Structure  (3) 2016.08.20
Enum  (0) 2016.08.17
정렬 (Comparable, Comparator, Ordering)  (0) 2016.08.16
Serializable  (0) 2016.08.15
Synchronized  (0) 2016.08.15
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함