JAVA Hash Set에 대한 고찰 (equals, hashcode, 동일, 동등)

Yunny.Log ·2023년 3월 23일
0

JAVA

목록 보기
28/29
post-thumbnail

Hash Set 문제상황

분명 HashSet에 이미 존재하는 객체인데, contains가 false로 나타나고, 계속해서 중복된 객체가 Set에 저장되는 이슈를 맞이했습니다.

  • HashSet으로 선언한 코드는 아래와 같습니다.
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Product extends EntityDate {
    @OneToMany(
            mappedBy = "product",
            cascade = CascadeType.PERSIST,
            orphanRemoval = true
    )
    private final Set<ProductItem> items = new HashSet<>();

HashSet 점검 코드

  • HashSet의 기능에 대한 점검 및 탐구를 하고자 아래 코드를 실행해보았습니다.
import java.util.HashSet;

public class Mystery2 {

	public static void main(String args[]) {
		class Dog {
			String color;

			public Dog(String s) {
				color = s;
			}
		}

		HashSet<Dog> dogSet = new HashSet<Dog>();
		dogSet.add(new Dog("white"));
		dogSet.add(new Dog("white"));

		System.out.println("We have " + dogSet.size() + " white dogs!");

		if (dogSet.contains(new Dog("white"))) {
			System.out.println("We have a white dog!");
		} else {
			System.out.println("No white dog!");
		}
	}
}

윗 코드에 대한 예상

이미 Set안에 white dog가 있으니
첫 white dog만 저장되고,
두번째 white dog는 누락돼서

=> We have a 1 white dogs
=> We have a white dog!

이렇게 두 줄이 출력할 것이다.

!! 그러나 예상은 모조리 빗겨갔습니다.

결과

자바의 동등성(equals), 동일성(hashcode)

  • HashSet을 적절히 사용하려면 , 자바의 동등성과 동일성에 대해 알아야 합니다.
  • Java에서 Identity와 Equality라는 개념이 존재합니다.
  • 프로그램은 메모리에 할당되어 실행됩니다.
    - 이때 같은 프로그램이더라도 다른 메모리에 올라간다면, 이를 동일하지 않은 것으로 얘기합니다. 즉 주소가 다르면 같지 않다는 것입니다.
  • 이때 hashcode - Identity(동일성)을 가리키고, equals - Equality(동등성)을 가리킵니다.

자바의 HashSet에서의 hashcode, equals의 재정의

  • 위에서 배운 개념을 바탕으로 재정의를 했습니다.
  • HashSet은 hashcode(디폴트는 메모리주소) + equals(디폴트는 같은 주소) 가 같을 때 동일한 객체로 인식한다는 것을 고려했습니다.
  • 제가 원했던 HashSet의 방향은 객체의 아이디가 같으면 동일하다고 인식하길 바랬던 것이기에, hashcode를 생성할 시 객체의 복합키 기준으로 code를 반환하게 했습니다.
  • 또한 equals(동등)도 hashcode 기준으로 비교하며 HashSet이 같은 아이디를 가진 객체는 같은 놈이라는 것을 인식할 수 있게 코드를 수정해주니, 제가 원하던 방향으로 정상 작동했습니다.

    @Override
    public int hashCode() {
        return Objects.hash(product.getId().toString() + item.getId().toString());
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof ProductItem)) {
            return false;
        }
        ProductItem productItem = (ProductItem) o;
        return Objects.equals(this.hashCode(), productItem.hashCode());
    }

키워드

JAVA의 동등성, 동일성 , equals, hashCode

REFERENCE

https://mangkyu.tistory.com/101

https://leoheo.github.io/java-hashcode-equlas/

https://stackoverflow.com/questions/47908818/hashset-item-equals-but-hashset-doesnt-contains

0개의 댓글