코테를 대비하기위해서 Collection 프레임워크를 공부하다가,
hashcode와 equals 함수의 재정의에 대해 공부를 하게 되었다.
다들 한번씩 개발 도중에 메소드 오버라이딩 하면서, 이와 같은 창을 본 적이 있을 것이다.

나도 그랬지만 용도가 뭔지 모르고, 무심코 넘겼을것이다.
오늘은 이 메소드에 대해 알아보고 기록해보고자 한다.
hashcode()와 equals() 메소드는 주로 동등비교에 사용된다.
우선 자바에서 두 객체를 비교한다는 것에는
동등성(equality)비교와 동일성(identity)비교가 있다.
동일성 비교에서는 자료형에 따라 달라지는데,
원시 타입(primitive type)과 참조 타입(reference type)에 따라 그 용도가 달라진다.
int a = 10;
int b = 10;
System.out.println(a == b); // true
원시타입은 단순히 변수가 저장된 메모리에 값 자체를 저장하므로,
==는 곧 값비교가 된다.
참조타입은 변수가 저장된 메모리에 객체의 주소 값을 저장하므로 ==는 주소값 비교한다.
변수 a와 b는 값은 같지만, 엄연히 다른 객체로 간주된다.
String a = new String("hello");
String b = new String("hello");
System.out.println(a == b); // false
물리적인 객체는 달라도, 값이 같으면 같다고 비교하는 연산이고,
eqauls() 메소드를 사용하여 판단한다.
참조타입에서만 사용한다.
String a = new String("hello");
String b = new String("hello");
System.out.println(a.equals(b)); // true
Object equals() 함수는 기본적으로는 동일성을 비교한다.

하지만 동일성은 충분히 ==로 비교 가능하므로, 우리는 이 함수를 오버라이딩하여 동등성을 비교하는 것으로 바꿔서 사용한다.
그리고 실제로 String Class에서는 이미 자동으로 오버라이딩 되어 있어,

이전 예시에서 보여줬던 것 처럼 동등성 비교가 적용이 되는 것이다.
특히, 이 둘은 Hash기반 Collection 프레임워크에 사용된다고 할 수 있다.
Set Collection은 객체의 저장 순서가 상관없고, 중복이 허용되지 않는 특징을 가진다. 그 중 대표적인 클래스인 hashSet를 살펴보자.
그 전에,
우리가 String 객체를 만든다고 생각을 했을 때
- String str1 = new String("a");
- String str2 = new String("a");
이 둘은 엄연히 다른 "객체"임을 알 것이다.
하지만, hashSet에서는 동일한 객체란 꼭 같은 인스턴스를 의미하지는 않는다.
그것은 hashSet의 동일성 판단 과정 때문인데,

와 같은 과정을 따르고,
hashCode()는 일단 객체의 메모리 주소값을 return하는 함수임을 생각하자.
실제로 Object Class의 코드를 까봐도 알 수 없었다.

하지만,
난 저 flow에서 이상한 점을 발견했다.
hashcode가 같으면 그냥 같은거니까 같은 객체로 생각하면 안되나? 왜 굳이 한번 더 equals()로 비교하는거지???
그에대한 대답은 이 해시코드는 고유값이 아니라는 점이다.
hashCode값은 객체의 "값"을 기준으로 만들어 지기 때문에, 내용이 같은 객체라면 동일한 해시코드가 나와서 해시 기반 자료구조에서 제대로 동작할 수 있다.
하지만 객체의 값이 달라도 해시같이 같은 경우가 있는데
hashCode는 무한한 객체를 유한한 숫자 공간(int = 약 43억 개) 안에 매핑해야 하기 때문에, 서로 다른 객체가 같은 해시코드를 가질 수도 있다.
이를 해시 충돌이라고 한다. 이 해시충돌이 일어날 수 있기 때문에 한 번더 equals() 함수를 이용해 판단하는 것이다.
1. hashCode 함수는 같은 값을 가진 객체는 항상 해시 같은 값이 나오도록 오버라이딩 해야한다.
equals()가 true인 두 객체는 반드시 같은 hashCode()를 가져야 한다.
그렇지 않으면 HashMap, HashSet 같은 해시 기반 컬렉션에서 예상치 못한 오류가 발생할 수 있다.
hashCode를 적절하게 오버라이딩 하지 않을 때는 아래왜 같은 오류가 발생.
Set<Person> set = new HashSet<>();
set.add(new Person("Alice"));
set.add(new Person("Alice"));
System.out.println(set.size()); // 2 → 중복인데도 둘 다 들어감
2. equals 함수는 동등성 비교로 오버라이딩 해야한다.
3. 해시 충돌을 피할 수 없기 때문이다.