본문 바로가기
JAVA

equals,hashCode 알아보기

by 봄석 2019. 10. 1.

equals,hashCode 알아보기

equals메소드와 hashcode메소드는
Object 클래스의 메소드입니다.
Object는 상속 관계상 가장 위에 있기 때문에 (모든 클래스가 Object를 상속)
어떤 객체라도 Object의 메소드인 equals와 hashcode를 사용할 수 있게 됩니다.

 

 

ex) equals ,hashcode 출력해보기

Object object1 = new Object();
Object object2 = new Object();
Object object3 = new Object();
Object object4 = new Object();

println("object1.equals(object2) result is " + object1.equals(object2));
println("object1.equals(object3) result is " + object1.equals(object3));
println("object1.equals(object4) result is " + object1.equals(object4));
println("");
println("object1 " + object1.hashCode());
println("object2 " + object2.hashCode());
println("object3 " + object3.hashCode());
println("object4 " + object4.hashCode());
object1.equals(object2) result is false
object1.equals(object3) result is false
object1.equals(object4) result is false

object1 796533847
object2 1449621165
object3 1627960023
object4 357863579

서로다른 Object를  equals로 비교했을때 false를 리턴하고

해시코드를 보았을때 모두 다른것을  볼 수 있습니다.

 

ex2) String을 equals ,hashcode 출력해보기

String str1 ="Hello world";
String str2 ="Hello world";
String str3 =new String("Hello world");
String str4 =new String("Hello world");


println("str1.equals(str2) result is " + str1.equals(str2));
println("str1.equals(str3) result is " + str1.equals(str3));
println("str1.equals(str4) result is " + str1.equals(str4));
println("");
println("str1 " + str1.hashCode());
println("str2 " + str2.hashCode());
println("str3 " + str3.hashCode());
println("str4 " + str4.hashCode());
println("");
println("str1==str2 " + (str1==str2));
println("str2==str3 " + (str2==str3));
println("str3==str4 " + (str3==str4));

 

str1.equals(str2) result is true
str1.equals(str3) result is true
str1.equals(str4) result is true

str1 -832992604
str2 -832992604
str3 -832992604
str4 -832992604

str1==str2 true
str2==str3 false
str3==str4 false

st1 == str  같은 문자열을 다른 변수에 바로 대입할 경우 같은 주소를 갖는다는 것도 확인가능합니다,

str3, str4처럼 new를 이용하여 생성하면 새로운 주소에 새로운 객체가 생깁니다, 쉽게 "Hello world"를 다른 주소에 새롭게 저장합니다

 

 

"Hello world"를 입력하여 문자열을 만들면

비교했을대 모두 true입니다.

눈여겨 보아야 하는 부분은 hashCode가 모두 같다는 것입니다.

 

String클래스에 있는 hashcode메소드는
Object클래스의 hashcode와는 달리 새롭게 정의되어 있어,

위와 같은 결과가 나오게 해줍니다.

아래에서 좀더 자세히 봐보도록 하겠습니다.

 

 

String의 값이같을때 new를이용하여 새로운 주소에 만들었음에도 해시코드가 같은이유 알아보기

간단한 사람클래스를 예로 알아보도록 하겠습니다.

public class People {
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

 

비교해보기

People people1 = new People("Kim", 20);
People people2 = new People("Kim", 20);

println("people1.equals(people2) result is " + people1.equals(people2));

같은 데이터를 같이는 people 객체를 두개 생성하여 비교하여봅니다.

 

people1.equals(people2) result is false

이상하게 People 클래스의 내용이 같으므로 equals로 비교하였을때 true 가 나올것을 예상했지만 값이 다릅니다.

 

바로 두객체가 같은객체임을 equals메소드로 비교하려면, equals메소드를 수정해야 하는것입니다!

 

equals메소드를 오버라이드하여 재정의 해보도록 하겠습니다.

public class People {
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof People) {
            People people = (People) obj;
            return (age == people.age) && (name.equals(people.name));
        }else{
            return false;
        }
    }
}

 

아까와 같은 비교코드를 실행해보았을때 아래처럼  true 를 리턴하는것을 볼 수 있습니다.

people1.equals(people2) result is true
people1 hashCode 1449621165
people2 hashCode 1627960023

하지만 두 객체의 hashCode를 보게되면 다릅니다.

 

비교는 같게 나왔지만 해시코드가 다르다 ..? 

뭔가 이상한것을 눈치채셨나요 ?

hashCode의 의미를 해치고 있는 것입니다.

 

People 클래스의 두 객체는 같은객체이므로 hashCode가 같아야만 두객체가 같다라는 의미를 가지게 됩니다.

그렇다면 ?

 

  @Override
    public int hashCode() {
        return age + name.hashCode();
    }

해시코드를 재정의하여 위와같이 수정한 후 결과를 봐보겠습니다.

 

people1.equals(people2) result is true
people1 hashCode 75459
people2 hashCode 75459

올바르게 나온것을 확인할 수 있습니다.

 

 

 

즉, 위에서 보았던 new String()으로 생성한 객체들은 내부에서 hashCode를 재정의하여주고 있는 것입니다.

 

그럼 더 생각해보아서

 

Q. hashCode가 같다면, equals가 반드시 트루인가 ??

답은 아닙니다.

 

실제 String의 경우 서로 다른 문자열이 (equals리턴값은 false)이지만 같은 hashCode를 리턴하는 경우가 생깁니다.

 hashCode의 값은 객체마다 유일한 값이아니라는겁니다.

 

그럼 hashCode는 왜필요한것일까요 ?

먼저 hashCode를 이용하여 같은객체가있는지 먼저 비교하고, 그다음 equals로 비교하는것입니다.

이렇게 비교하는 이유는 , 수만가지의 String 데이터중에 "Hello world"라는 값을 찾는것과 

hashcode로 먼저 비교하여 경우의수를 줄이고 그다음 "Hello world"를 찾는것이 더 효과적이기 때문입니다.

 

 

 

 

정리  자바에서 정의하고있는 hashCode규약

  • equals() 메소드가 true 이면 , 두 객체의 hashCode값은 같아야한다.
  • equals() 메소드가 false 이면 , 두 객체의  hashCode값이 꼭 다를 필요는 없다.

'JAVA' 카테고리의 다른 글

Java 8 - Function Interface  (3) 2019.10.13
Java 8 - Interface바뀐점을 알아보기  (0) 2019.10.11
Lombok 알아보기  (4) 2019.09.15
boilerplate  (2) 2019.09.15
Java - Atomic변수  (0) 2019.09.02

댓글