equals () 와hashcode () 에 대해 당신이 알아야 할 모든 것

7216 단어

1. equal()과 ==의 차이는 무엇입니까?


equals () 방법을 이해하려면 반드시 ==부터 말해야 한다.
==의 역할은 매우 간단하다. 바로 두 대상의 주소가 같은지 아닌지를 판단하는 것이다(기본 데이터 유형은 값을 비교하고 인용 데이터 유형은 주소를 비교한다).
그럼 equal () 방법은요?이것은 Object 객체의 한 방법입니다. 모든 클래스가 Object에서 상속되기 때문에 모든 클래스에 equal () 방법이 있습니다.Object의 원본 코드에서 equal () 방법이 어떻게 생겼는지 볼 수 있습니다.
public boolean equals(Object obj) {
        return (this == obj);
    }

너는 이것이 바로 ==과 같지 않다고 생각할 것이다??네, 확실히 똑같습니다. 그런데 왜 equals () 방법을 더 만들어야 합니까?사실 equals () 방법은 자바가 우리에게 다시 쓰라고 제공하는 것이다.일반적으로 우리는 equals () 방법을 사용하여 두 대상의 내용이 같은지 비교하는데 다음과 같은 예를 볼 수 있다.
/**
 * @Author shenghai
 * @Date 4/19 19:03
 */
public class test {
    public static void main(String[] args) {
        Person p1 = new Person("abc", 111);
        Person p2 = new Person("abc", 111);
        System.out.printf("p1.equals(p2) : %s
", p1.equals(p2)); System.out.printf("p1==p2 : %s
", p1==p2); } private static class Person { int age; String name; public Person(String name, int age) { this.name = name; this.age = age; } @Override public boolean equals(Object obj){ if(obj == null) { return false; } if(this == obj) { return true; } // if(this.getClass() != obj.getClass()) { return false; } Person person = (Person) obj; return name.equals(person.name) && age==person.age; // name equals String } } } /** * : * p1.equals(p2) : true * p1==p2 : false */

이를 통해 알 수 있듯이 Person 대상에서 우리는 equals() 방법을 다시 썼고 주요 논리는 마지막 문장에서 Person류의 필드nameage가 모두 같은지 판단했다.이렇게 해서 우리는 새로운 규칙을 사용하여 두 Person 대상의 주소가 같은지 아닌지를 판단하는 것이지 원시적인 ==을 사용하여 두 Person 대상의 주소가 같은지 판단하는 것이 아니다.

2.hashCode()의 역할


equals ()와 마찬가지로 hashCode () 도 Object 클래스의 한 방법으로, 이것은 native 방법 (즉 JNI 방법, Java Native Interface, 원본 코드는 C로 쓴 것) 이다.
public native int hashCode();

hashCode () 의 역할은 해시 코드를 가져오는 것입니다. 이것은 실제적으로 int 정수를 되돌려줍니다.이 해시 코드의 역할은 그 대상이 해시 표에 있는 위치를 확정하는 것이다.따라서hashCode()는 해시 테이블에서만 사용할 수 있고 다른 상황에서는 쓸모가 없다.이곳의 해시표는 해시맵, 해시셋, 해시테이블 등을 포함한다.
그럼 왜 해시코드가 있는 거죠?
조금 간단한 해시셋을 예로 들면, 대상을 해시셋에 넣을 때, 해시셋은 대상의hashCode 값을 먼저 계산해서 대상이 들어간 위치를 얻고, 이 위치의 다른 이미 들어간 대상의hashCode 값과 비교할 때, 이때는 이퀄스 () 방법을 사용해서hashCode와 같은 대상이 정말 같은지 확인한다. (즉 우리가 다시 쓴 이퀄스 () 방법으로 판단한다.만약 "정말 같다"면, HashSet은 작업에 성공하지 못하게 할 것입니다.만약 같지 않다면 해시가 충돌하여 이 대상을 해시를 다른 위치로 옮길 것이다.

3. hashCode()와 equals()의 관계


여기에는 두 가지 상황으로 나누어 토론해야 한다.

3.1 해시 테이블에서 사용하지 않음


여기서 말한 것은 우리가 Obj 대상이 있다고 가정하지만 HashSet,Hashtable,HashMap 등 본질이 산목록의 데이터 구조에서 이 대상을 사용하지 않았다는 것이다.
그럼, 이런 상황에서 당신이 어떻게 equals () 방법을 다시 쓰든hashCode () 방법과 아무런 관계가 없습니다!!

3.2 해시 테이블에서 사용


그러나 만약에 우리가 해시표를 사용한다면 우리는 두 대상이 같다면 그것들의hashCode값은 반드시 같다는 것을 보증해야 한다. (여기서 같은 것은 equals()를 통해 두 대상을 비교할 때true로 돌아가는 것을 가리킨다.)
따라서 이 경우 두 대상이 동일한지 판단하려면 equals() 방법 외에 hashCode() 방법도 다시 써야 한다.
만약에 우리가 equals () 방법만 다시 썼을 뿐 hashCode () 방법을 다시 쓰지 않았다면, 두 대상이 같을 때 (equals () 방법이 되돌아오는 true) 에도 이 두 대상은 같은 주소로 돌아갈 방법이 없다. 이럴 때 해시표를 사용하면 문제가 생길 수 있다.
예를 들면 다음과 같습니다.
import java.util.HashSet;

/**
 * @Author shenghai
 * @Date 4/20 13:20
 */
public class test1 {
    public static void main(String[] args) {
        //  Person ,
        Person p1 = new Person("abc", 111);
        Person p2 = new Person("abc", 111);
        Person p3 = new Person("ccc", 200);

        //  HashSet 
        HashSet set = new HashSet<>();
        set.add(p1);
        set.add(p2);
        set.add(p3);

        //  p1   p2,  hashCode()
        System.out.printf("p1.equals(p2) : %s; p1(%d) p2(%d)
", p1.equals(p2), p1.hashCode(), p2.hashCode()); // set System.out.printf("set:%s
", set); } private static class Person { int age; String name; public Person(String name, int age) { this.name = name; this.age = age; } @Override public boolean equals(Object obj) { if(obj == null) { return false; } if(this == obj) { return true; } // if(this.getClass() != obj.getClass()) { return false; } Person person = (Person)obj; return name.equals(person.name) && age==person.age; } } } /** * : * p1.equals(p2) : true; p1(460141958) p2(1163157884) * set:[euqalsAndHashcode.test1$Person@74a14482, euqalsAndHashcode.test1$Person@4554617c, * euqalsAndHashcode.test1$Person@1b6d3586] */

이럴 때, 비록 우리가 equals () 방법을 사용하면 되돌아갈 수 있지만 true.그러나 분명히 p1과 p2를HashSet에 추가할 때HashSet은 이 두 대상이 같지 않다고 판정했다.
왜 이런 상황이 생겼을까?이것은 p1과 p2의 내용은 같지만 그것들의hashCode()가 같지 않기 때문이다.그래서 HashSet은 p1과 p2를 추가할 때 서로 다르다고 생각한다.그러니 이제 해시코드 () 방법을 다시 써 봅시다.
import java.util.HashSet;
import java.util.Objects;

/**
 * @Author shenghai
 * @Date 4/20 13:20
 */
public class test2 {
    public static void main(String[] args) {
        //  Person ,
        Person p1 = new Person("abc", 111);
        Person p2 = new Person("abc", 111);
        Person p3 = new Person("ccc", 200);

        //  HashSet 
        HashSet set = new HashSet<>();
        set.add(p1);
        set.add(p2);
        set.add(p3);

        //  p1   p2,  hashCode()
        System.out.printf("p1.equals(p2) : %s; p1(%d) p2(%d)
", p1.equals(p2), p1.hashCode(), p2.hashCode()); // set System.out.printf("set:%s
", set); } private static class Person { int age; String name; public Person(String name, int age) { this.name = name; this.age = age; } @Override public boolean equals(Object obj) { if(obj == null) { return false; } if(this == obj) { return true; } // if(this.getClass() != obj.getClass()) { return false; } Person person = (Person)obj; return name.equals(person.name) && age==person.age; } @Override public int hashCode() { return Objects.hash(age, name); } } } /** * : * p1.equals(p2) : true; p1(100756) p2(100756) * set:[euqalsAndHashcode.test2$Person@18994, euqalsAndHashcode.test2$Person@19bfc] */

equals () 방법과 hashCode () 방법을 다시 쓰면 모든 것이 문제없습니다 ~
마지막으로 equals () 방법과 hashCode () 방법에 관한 규정을 요약해 보겠습니다.
  • 만약 두 대상이 같다면 그것들의hashCode도 반드시 같을 것이다.
  • 만약 두 대상이 같다면 각각 equals () 방법을 호출하면 반드시 true 되돌아온다.
  • 만약 두 대상이 같은hashCode 값을 가지고 있다면 그것들도 반드시 같지 않다.
  • 해시표를 사용하고 euqals () 방법이 다시 쓰여지면hashCode () 방법도 다시 써야 한다.
  • 좋은 웹페이지 즐겨찾기