[Java] HashSet과 HashMap에서 equals() hasCode()를 재정의 해주어야 하는 경우

📌equals(),hashcode()

  • 자바 최상의 Object 클래스에 equals()와 hascode() 메서드가 있다.
  • Object의 equals는 객체의 주소를 비교하여 같은 객체인지 확인한다.
public boolean equals(Object obj){
    return (this == obj);
}

✅에제1 오버라이딩 하기전

Person클래스는 name과 age를 맴버변수로 같고 name, age가 같으면 같은 사람으로 인식하도록 하려는 의도로 작성하였다.

public class EX11_11 {
    public static void main(String[] args) {
        HashSet set = new HashSet();

        set.add("abc");
        set.add("abc"); //중복이라 저장안됨
        set.add(new Person("David", 10));
        set.add(new Person("David", 10));

        System.out.println(set);
    }
}

//equals () 와 hashCode()를 오버라이딩해야 HasSet이 바르게 동작.
class Person {
    String name;
    int age;

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

    public String toString() {
        return name + ":" + age;
    }
}

/*출력
[abc, David:10, David:10]
*/

결과를 보면 두인스턴스의 name,age가 같음에도 불구하고 서로 다른것으로 인식하여 David:10이 두번 출력되었다.
이 클래스의 작성의도대로 두인스턴스를 같은 것으로 인식하게 하려면 어떻게 해야할까?


✅에제2 오버라이딩

public class EX11_11 {
    public static void main(String[] args) {
        HashSet set = new HashSet();

        set.add("abc");
        set.add("abc"); //중복이라 저장안됨
        set.add(new Person("David", 10));
        set.add(new Person("David", 10));

        System.out.println(set);
    }
}

//equals () 와 hashCode()를 오버라이딩해야 HasSet이 바르게 동작.
class Person{
    String name;
    int age;

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

    public String toString() {
        return  name + ":" + age;
    }

    @Override
    public boolean equals(Object obj ==  person) {
       if(!(obj instanceof Person)) return false;

       Person p = (Person) obj;
        // 나자신(this)의 이름과 나이를  p와 비교
       return  this.name.equals(p.name) && this.age == p.age;
    }

    @Override
    public int hashCode() {
        // int hash(Object.. values); //....>은 가변인자
        return Objects.hash(name, age);
    }
}

/*출력
[David:10, abc]

*/
  1. HashSet의 add()는 새로운 객체를 추가 하기 전에 기존에 저장된 객체와 같은 것인지 확인하기 위해 저장할 객체의 equals()와 hashcod()를 호출한다.
  2. 현재 eqauls는 오버라이딩 되어있지 않아 객체 주소를 비교한다.
  3. 오버라이딩 하여 Person클래스에서 두 인스턴스의 name과 age가 같으면 true를 반환하도록 equals를 오버라이딩 하였다.
  4. Objects클래스의 hash()를 이용해서 메스의 괄호 안에 클래스의 인스턴스 변수들을 넣어 오버라이딩하였다.
    결과값 =>[David:10, abc] 출력

✅정리

  • Object의 equals와 hashCode는 객체의 주소를 가지고 계산을 한다.
  • 우리는 equals를 객체의 주소가 아닌 다른 비교로 바꾸어주어야 할 경우가 있다.
  • 이떄 HashSet,HashMap뿐만 아니라 haschode로도 객체를 비교하기떄문에 hashCode도 재정의 해주어야한다.

ref https://ksabs.tistory.com/188

Categories:

Updated:

Leave a comment