사용자 정의 객체의 동등성을 비교하기 위해 equals와 hashCode를 재정의 해야함
String, ArrayList, LinkedList, Set등 사전에 정의된 객체나 컬렉션은 equals와 hashCode가 재정의 되어 있다.
원시타입은 객체가 아닌 값이기에 동일성 비교를(==) 통해 중복을 판단한다.
equals만 재정의 했을 경우
서로 같은 객체가 서로 다른 해시값을 가질 수 있기 때문
hashCode만 재정의 했을 경우
서로 같은 해시값이지만 동등한 객체가 아닐 수 있음
class EqualsTest{
// 이너 클래스에 equals와 hashCode 재정의 한 경우
main(){
Set<Location> hs = new HashSet<>();
hs.add(new Location(1, 2));
hs.add(new Location(1, 2));
System.out.println(hs.size());
// 이너 클래스에 equals와 hashCode 재정의 안한 경우
Set<Loc> hs2 = new HashSet<>();
hs2.add(new Loc(1, 2));
hs2.add(new Loc(1, 2));
System.out.println(hs2.size());
}
class Location{
int y;
int x;
public Location(int y, int x) {
this.y = y;
this.x = x;
}
@Override
public boolean equals(Object o) {
// 두 객체의 주소가 같으면 서로 같은 객체
if (this == o) return true;
// 비교하려는 객체 o가 null이거나
// 두 객체가 서로 다른 클래스인경우
// 서로 다른 객체
if (o == null || getClass() != o.getClass()) return false;
// Object 클래스에서 자식 클래스로 형변환
Location location = (Location) o;
// 두 객체가 같은 값을 갖는지 체크
return y == location.y && x == location.x;
}
@Override
public int hashCode() {
return Objects.hash(y, x);
}
}
class Loc{
int y;
int x;
public Loc(int y, int x) {
this.y = y;
this.x = x;
}
}
}
출력: 1
2
List<Integer> ls = new ArrayList<>();
List<Integer> equality = new ArrayList<>();
List<Integer> different = new ArrayList<>();
List<Integer> identity = ls;
ls.add(1);
ls.add(2);
equality.add(1);
equality.add(2);
different.add(2);
different.add(1);
/*
ls = [1, 2]
equality = [1, 2]
different = [2, 1]
identity = [1, 2]
*/
동등성 비교 (equals 메서드):
동일성 비교 (== 연산자):