Object 클래스에선 equals() 는 비교 연산자인 == 과 동일한 결과를 리턴한다.
오로지 객체의 주소값이 같은지를 확인하는 것이다.
자바에서는 두 객체를 동등비교 할때 equals() 를 주로 사용한다.
그러나 String에서는 이것을 재정의하여 사용한다.
equals 는 논리적으로 동등하면 true 아니면 false
논리적 동등?
둘의 참조값이 다르더라도 객체 내부 value 는 같다.
- String 에서는 equals() 메소드를 재정의해서 번지비교가 아닌 문자열 '값'을 비교한다.
- 객체의 인스턴스 주소값 비교는 ==
- 객체 내부의 값의 비교는 equals()메소드로
자바 해시 코드란?
객체를 식별하는 하나의 정수값이다.
Object의 hashCode() 메소드는 객체의 메모리 번지를 이용해서 해시코드를 리턴한다.
그렇기 때문에 객체마다 다른 값을 가지고 있다.
객체의 값을 동등성 비교시 hashCode()를 오버라이딩할 필요성이 있다.
컬렉션 프레임워크에서 HashSet, HashMap, HashTable 은 다음과 같은 방법으로 두 객체가 동등한지 비교한다.
hashCode()
메소드 실행해서 리턴된 해시코드 값이 같은지 확인, 해시코드 값이 다르면 다른 객체로 판단
해시코드 값이 같으면
equals()
메소드로 다시 비교, 이 2개가 모두 맞아야만 동등 객체로 판단한다.
즉) 해시코드 값이 다른 엔트리끼리는 동치성 비교조차 하지 않는다.
HashTable
<key, value> 형태로 데이터를 저장한다. 이 때 해시 함수를 이용하여 key값을 기준으로 고유한 식별값은
해시값을 만든다.
이 해시값을 버킷에 저장한다. 하지만?!?!?!?!? HashTable의 크기는 한정적이기 때문에 서로다른 객체라 하더라도 같은 해시값을 갖게 될 수도 있다. 이것을 해시충돌(Hash Collisions) 라고 한다.
이처럼 같은 해시값의 버킷안에 다른 객체가 있는 경우 equals 메서드가 사용된다.
위 그림을 보면 3개의 Entry 객체가 있으며 서로 같은 해시값을 같는다. 그래서 hashCode는 같은 값을 리턴한다
하지만 서로 다른 객체이기 때문에 equals 메서드는 false를 리턴한다
결국 equals() 와 hashCode() 를 같이 재정의 해야하는 이유
위의 그림과 같이 hashCode()를 재정의 하지 않으면 서로 다른 값 객체라도 해시값이 같을 수 있다.
equals()를 재정의 하지 않으면 hashCode()가 만든 해시 값을 이용하여 객체가 저장된 버킷을 찾을수는 있지만
해당 객체가 자신과 같은 객체인지 비교할 수 없기 때문에 null을 리턴하게 된다. 따라서 원하는 객체를 찾을수 없다.
이런 이유때문에 둘다 재정의해서 논리적 동등 객체일 경우 동일한 해시코드가 리턴되도록 해야한다.
'Language > 자바' 카테고리의 다른 글
[자바]10. JVM 의 작동원리 (0) | 2021.07.26 |
---|---|
[자바]9. 자바 명명 규칙 정리 (0) | 2021.07.13 |
[자바] 7. 컬렉션 프레임워크 (0) | 2021.04.06 |
[자바]6. 표준API의 함수적 인터페이스 (0) | 2021.04.03 |
[자바]5. 람다(Lamda) (0) | 2021.04.02 |