반응형

HashSet - 예제

  • HashSet은 객체를 저장하기전에 기존에 같은 객체가 있는지 확인
    같은 객체가 없으면 저장하고, 있으면 저장하지 않는다.
  • boolean add(Object o)는 저장할 객체의 equals()와 hashCode()를 호출
    equals()와 hashCode()가 오버라이딩 되어 있어야 함

 

HashSet은 순서를 유지하지 않고, 중복을 허용하지 않는다.
그래서 HashSet과 같은 Set인터페이스를 구현한 클래스는 객체를 저장하기 전에 기존에 같은 객체가 있는지 확인한다.
그래야 중복된 것을 저장하지 않을 수 있기 때문이다.

그래서, Set에 객체를 저장하는 메서드 add(Object o)는 저장하기전에 객체의 equals()hashCode()를 호출해서 중복되는게 있는지 확인한다.

위 코드를 보자,
이름이랑 나이를 iv로 가지고 있는 Person이라는 클래스가 있을 때,
만약에 add()메서드로 Person객체를 추가한다고 하면,
Person 클래스에서 equals()와 hashCode()를 호출한다.
그런데, Person클래스에는 equals()와 hashCode()가 없다.
사실은, equals()와 hashCode()는 Object클래스에서 온 것이다.
즉, Person클래스에 써있지는 않지만, Object클래스에서 상속되어 있는 상태라는 것이다.
그래서 equals()와 hashCode()를 호출할 수 있다.

그런데, 문제는 equals()와 hashCode()가 오버라이딩 되어있지 않으면, HashSet이 제대로 동작하지 않는다는 것이다.
equals()와 hashCode()를 오버라이딩해야 중복을 확인할 수 있다.

원래는 equals()만 오버라이딩 해도 되지만, hashCode()도 같이 오버라이딩 하는 것이 정석이다.

HashSet처럼 Hash가 붙은 클래스들은 내부적으로 hashCode()를 이용하는데,
HashSet같은 클래스를 자주 사용하기 때문에, equals()를 오버라이딩 할 때, hashCode()를 같이 오버라이딩 하는 것이 정석이다.

어떤 식으로 오버라이딩 하는지 코드를 살펴보자.

equals()는 iv 값들을 다 비교하도록 오버라이딩 한다.
만약, 비교하려는 Object가 Person의 인스턴스가 아니면 비교할 필요가 없어서 그러한 경우에는 return false인 것이고,
만약에 Person 인스턴스이면, 형변환을 할 수 있는데, (형변환을 하기전에 바로 이전에 설명한 것처럼 instanceof로 체크해야 한다는 점을 명심하자) 형변환을 해주는 이유는, 해당 참조변수로 Person클래스의 멤버를 사용하기 위함이다.

그리고, 비교할 때는, this와 obj를 비교한다.  객체 자신과 매개변수로 지정된 객체를 비교한다는 것이다.

hashCode()는 String의 hashCode()메서드를 호출한 것인데,
name은 String이고, age는 int이므로 둘이 더하면 결과가 String이 나온다. 즉, String클래스가 가지고 있는 hashCode()를 사용해서 만들었는데,  이것은 옛날 방식이다.

요즘에는 어떻게 하냐면,
return Objects.hash()이런 식으로 사용한다.
Objects클래스의 hash()메서드를 이용하고, 매개변수 안에 (name, age)넣는 식으로 이용하면 된다.

원래는 직접 우리가 직접 만들어줘야하는데, Objects클래스가 제공되서 좀더 편리하게 작성할 수 있게 도와준다.

 

[Ex11_11]

 

[Ex11_12]

반응형

'JAVA' 카테고리의 다른 글

TreeSet (2)  (0) 2022.05.02
TreeSet (1)  (0) 2022.05.02
HashSet (1)  (0) 2022.05.01
Comparator와 Comparable  (0) 2022.05.01
Arrays  (0) 2022.04.30