Java - 1. JCF - equals(), hashCode()

갓김치·2020년 9월 16일
0

고급자바

목록 보기
5/47

Hash Function

  • 해시함수
  • 임의의 길이의 데이터를 고정된 길이의 데이터로 매핑해주는 함수
  • 해시함수에 의해 얻어지는 값: 해시값, 해시코드, 해시체크섬 또는 간단하게 해시

Hash- 들의 객체 비교

  • HashSet, HashMap, HashTable
  • 객체가 서로 같은지를 비교하기 위해 equals()메서드와 hashCode()메서드를 호출
  • 객체가 서로 같은지 여부를 결정하려면 두 메서드를 재정의 해야 한다.
  • HashSet, HashMap, HashTable에서는 객체가 같은지 여부를 데이터를 추가할 때 검사한다.

비교에 쓰이는 두 메서드

equals()

  • 두 객체의 내용(값)이 같은지 비교하는 메서드

hashCode()

  • 두 객체가 같은 객체인지를 비교하는 메서드

equals()와 hashCode()에 관한 규칙

    1. 두 객체가 같으면 반드시 같은 hash code를 가져야 한다.
    1. 두 객체가 같으면 equals()메서드를 호출했을 때 true를 반환해야 한다.
    • 즉, 객체a, b가 같다면 a.equals(b)와 b.equals(a) 둘다 true이어야 한다.
    1. 두 객체의 hash code가 같다고 해서 두 객체가 반드시 같은 객체는 아니다.
    • 하지만, 두 객체가 같으면 반드시 hash code 가 같아야 한다.
    1. equals()메서드를 override하면 반드시 hashCode()메서드도 override해야 한다.
    1. hashCode()는 기본적으로 Heap에 있는 각 객체에 대한 메모리 주소 매핑 정보를 기반으로 한 정수값을 반환한다.
    • 그러므로, 클래스에서 hashCode()메서드를 override하지 않으면 절대로 두 객체가 같은 것으로 간주될 수 없다.
    • hashCode()메서드에서 사용하는 '해싱 알고리즘'에서 서로 다른 객체에 대하여 같은 hash code값을 만들어 낼 수 있다. 그래서 객체가 같지 않더라도 hash code가 같을 수 있다.

예시

비교를 위해 만든 Person 클래스

class Person {
  private int id;
  private String name;

  public Person(int id, String name) {
      super();
      this.id = id;
      this.name = name;
  }

  public int getId() {
      return id;
  }

  public void setId(int id) {
      this.id = id;
  }

  public String getName() {
      return name;
  }

  public void setName(String name) {
      this.name = name;
  }

  @Override
  public int hashCode() { // id와 name이 같으면 같은 값이 나오도록 되어있음
      final int prime = 31; // 소수
      int result = 1;
      result = prime * result + id;
      result = prime * result + ((name == null) ? 0 : name.hashCode());
      return result;
  }

  @Override
  public boolean equals(Object obj) { // id와 name이 같으면 같은 값이 나오도록 되어있음
      if (this == obj)	// p1.equals(p1) 
          return true;  // 자기 자신이 매개변수니 당연히 같음
      if (obj == null) 	// p1.equals(null)
          return false; // null값랑 비교하니 당연히 다름
      if (getClass() != obj.getClass()) // p1과 p2의 클래스 정보 비교
          return false;			 
          				// 이제 본격 비교!!
      Person other = (Person) obj; // 1. object로 들어온걸 캐스팅해서 other 변수에 넣어줌
      if (id != other.id)          // 2. 기준 객체와 매개변수 객체의 변수값 비교
          return false;
      if (name == null) {
          if (other.name != null)
              return false;
      } else if (!name.equals(other.name)) // 이름 String 비교 위해 equals
          return false;
      return true;
  }
}

main

Person p1 = new Person(1, "홍길동");
Person p2 = new Person(1, "홍길동");
Person p3 = new Person(1, "이순신");

System.out.println("p1.equals(p2) : " + p1.equals(p2)); // true, 오버라이드. 값 같음 
System.out.println("p1 == p2 : " + (p1 == p2)); // false, 주소 다름
System.out.println();
Set<Person> set = new HashSet<>();

set.add(p1); // add하면서 중복검사
set.add(p2);

// p1, p2 등록 후 데이터: [1, 홍길동] 
// -> p1만 등록, p2는 중복이어서 등록 안됨.

set.add(p3)); // true

// p3 등록 후 데이터: [1, 홍길동], [1, 이순신]

set.remove(p2)); // true : p1이랑 p2랑 같다고 되어서 p1이 지워진 것

// remove(p2) 후 데이터: [1, 이순신]
profile
갈 길이 멀다

0개의 댓글