본문 바로가기

Android(Kotlin) Study A부터 Z까지 등반

==, ===, equals, hashcode란

원시 타입 vs 참조타입

하기에 앞서 원시타입고 참조 타입의 구분을 할 필요가 있다.

이전 스터디에서 정리하였던 primitive 타입 이외에 변수에 값을 저장하는 것이 아닌 객체의 주소를 저장하는 변수들을 참조타입이라고 한다. 대표적으로 String(문자열), 배열, 열거체, 클래스 인터페이스등이 있다.

동일성 : 두 오브젝트가 완전히 동일(같은 메모리 주소) , 여러개의 참조 변수를 보유

동등성 : 동일한 정보를 가지고 있는 오브젝트(메모리 주소가 아닌 각 오브젝트 기준으로 동일, int string 등등)

val a = String(StringBuilder("hello")) val b = String(StringBuilder("hello"))

println(a==b)

// true, 값만 똑같고 저장된 주소는 다름

println(a===b)

// false, 값도 같고 주소까지 똑같음

println(a.equals(b))

// true, 값만 똑같고 저장된 주소는 다름, ==이랑 같음

별개 이야기지만, 동적으로 많이 변하는 String은 StringBuilder를 통해서 생성해주면 동적으로 메모리가 할당되어 메모리를 보다 효율적으로 관리할 수 있다고 한다.

데이터 클래스도 생성시 hashcode(), equals() 함수 자동 생성, 왜냐하면 Object 클래스에 있는 함수이기 때문에!

https://beomseok95.tistory.com/248 - 해시코드, Equals 예제

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

답은 아닙니다.

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

val somethingItemOne = SomethingResponse(
    name = "name",
    age = 50,
    isSelected = false
)
val somethingItemTwo = SomethingResponse(
    name = "name",
    age = 50,
    isSelected = false
)

// 2 객체 비교
println("somethingItemOne == somethingItemTwo ${somethingItemOne == somethingItemTwo}")  //
println("somethingItemOne === somethingItemTwo ${somethingItemOne === somethingItemTwo}")
println("somethingItemOne hashCode ${somethingItemOne.hashCode()}")
println("somethingItemTwo hashCode ${somethingItemTwo.hashCode()}")

-output-

somethingItemOne == somethingItemTwo false
somethingItemOne === somethingItemTwo false
somethingItemOne hashCode 425918570
somethingItemTwo hashCode 2143192188

// 2 String 변수 비교
println("somethingItemOne.name == somethingItemTwo.name ${somethingItemOne.name == somethingItemTwo.name}")
println("somethingItemOne.name === somethingItemTwo.name ${somethingItemOne.name === somethingItemTwo.name}")
println("somethingItemOne hashCode ${somethingItemOne.name.hashCode()}")
println("somethingItemTwo hashCode ${somethingItemTwo.name.hashCode()}")

-output-

somethingItemOne.name == somethingItemTwo.name true
somethingItemOne.name === somethingItemTwo.name true
somethingItemOne hashCode 3373707
somethingItemTwo hashCode 3373707

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

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

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

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

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

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

  • equals() 메소드가 false 이면 , 두 객체의 hashCode값이 꼭 다를 필요는 없다.
  • Class에 equals를 정의했다면, 반드시 hashCode도 재정의해야 한다.
  • 2개 객체의 equals가 동일하다면 반드시 hashCode도 동일한 값이 리턴되어야 한다.
  • 이런 조건을 지키지 않을 경우 HashMap, HashSet 등의 컬렉션 사용 시 문제가 생길 수 있다.

참고로 나도 구글에서 공부하고 직접 쓰는 내용도 있지만 긁어오는 경우가 많다. 최대한 참고한 사이트를 올릴 생각이다. 양해바란다!

예제 참조:  https://thdev.tech/kotlin/2020/09/15/kotlin_effective_02/