Equals,HashCode 넌 알고있니?

1

너는 알고있니..?😏

오늘 있었던일이다.

  • latitude , longtitude가 선언 된 객체 20000개가 존재하고 리스트에 담겨져 있다.
  • contains() 연산자를 사용해서 객체 20000개안에서 있는지 없는지 확인하고싶다.

중요한건 contains()안에는 새로운 객체를 넣어서 비교해야하는것이다.
비교를 하게 되면 뭐가 나올까?

아쉽게도 Failed...😂😂

이걸 이해하려면 객체와 contains()가 뭔지부터 확인해야한다.

어렵지 않다.
기본적인것부터 가보자.

Java,Kotlin이 객체지향 언어이기 때문에 우리는 객체를 만들어서 다룬다.

객체를 만들면서 중요한점은 바로 독립적이라는 것이다.

이렇게 A객체와 B객체 , C객체는 정보가 공유되지 않는다.

내가 생각하기론 객체라는것은 포장 용지라고 이해하면 편한데, A와 B안에 있는것은 같은 장난감이지만,
A 와 B라는 포장용지떄문에 컴퓨터의 인식으로는 두개는 다르다고 판단한다.

이제 Contains()로 돌아가자.

public boolean contains(Object obj)
object-element to be searched for
Parameters: This method accepts a single parameter obj whose presence in this list is to be tested.
Return Value: It returns true if the specified element is found in the list else it returns false.

()안에 객체를 넣을경우, 해당 객체를 찾아서 있으면 True, 없으면 False를 뱉는다.

요점은 새로운객체도 값이 같으면 객체가 똑같다고 컴퓨터에게 알려주고 싶습니다.

논리적으로 표현하자면 아래의 코드와 같다.

        val example = mutableListOf<DataClass>().run{
            this.add(DataClass("퐁퐁이 노래해"))
            this.add(DataClass("퐁퐁이 노래안해"))
            this.add(DataClass("비아키스 옴멤메"))
            this.add(DataClass("호랑이 발냄새"))
           
        }
        
        
 example.filter {it.name == "퐁퐁이 노래해"}
 

객체 안의 인스턴스 변수들을 하나하나씩 비교해서 맞으면 같은객체면 Ok라고 판단하게 만들고 싶다.

이럴때 필요한것이 equals 이다.

equals
equals(Object obj)로 정의된 equals 메소드는 2개의 객체가 동일한지 검사하기 위해 사용된다.
eqauls에서 true가 떨어지게 되면 같은 객체라고 판단된다.

그래서 모든 객체를 비교하는 함수가 사용(예를 들어 contains)될때, equals 함수가 사용된다.
아래의 코드를 보자.

@Override
public boolean equals(Object obj) {

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false

        other as Champion

        if (id != other.id) return false
        if (key != other.key) return false
        if (name != other.name) return false
        if (title != other.title) return false
        if (blurb != other.blurb) return false
        if (info != other.info) return false
        if (image != other.image) return false
        if (tags != other.tags) return false
        if (partype != other.partype) return false
        if (stats != other.stats) return false

        return true
    }

    return false;
    
    //같은 객체면 OK, 클래스가 다르면 Fail, 다른 객체여도 값이 같으면 True
}

이렇게 equals를 재정의 해주면 다른객체일지라도 같은 객체로 인식하게 만들어준다.


와우 이제 다끝난것같나..?

Hash Collection 의 비교 원리

이렇게 List에서 변수의 값들이 같은 새로운 객체를 비교했을때 정상적으로 같은객체로 인식이 된다.

하지만 이상하게도 Hash를 쓰는 Collection(HashSet, HashMap, HashTable) 은 같은애들이라고 인식하지 않나보다.

분명 Set은 중복된 객체가 들어가지 않는다고 들었는데.. equals로 객체 비교를 정의해줬는데.... 😂😂😂

위의 표를 보면 Hash Collection은 equals를 확인하기전에 hashCode를 먼저 확인한다.

그래서 분명 같은 객체라고 만들었음에도 HashCode가 다르기 때문에 다르게 인식한다.
이제 그래서 HashCode도 Override 해주는 것이 좋은데, 아래의 링크를 통해 제너레이트 한것보다 더 우수하게 알고리즘을 짤수 있다.

해시코드 알고리즘을 더 빠르게 짜자

막 넣지 마세요.. 제발

EqualsHashCode의 재정의를 통해 다른객체를 같은 객체로 인식하는 방법을 오늘의 포스팅을 통해 배웠다.
근데 이 좋은 방법을 왜 객체 지향 언어에서는 Dafault값으로 지정하지 않는것일까?
기본적으로 객체의 참조 위치가 다르면 Pass하는 기본 방식보다 안의 값을 비교하는 방식이 최소 2배 이상은 느리기 때문이다.
그렇기 때문에 적재적소에 사용하는것 또한 개발자의 몫 아닐까..?

profile
쉽게 가르칠수 있도록 노력하자

2개의 댓글

comment-user-thumbnail
2022년 1월 8일

ㅋㅋㅋㅋㅋㅋㅋㅋㅋ잘 봤습니다 글이 너무 재밌네요

1개의 답글