1. 문제 상황

마인크래프트 길찾기 알고리즘 제작 중이었음

탐색 기준점으로 사용된 좌표는 두 번 이상 사용하지 않아야 함.

이를 위해 탐색 후보 좌표들을 리스트에, 탐색을 완료한 좌표들을 맵에 담아서 관리함

그리고 탐색 후보에 현재 좌표를 새롭게 추가할 때, 중복되는 좌표인지 확인하기 위해 현재 좌표 객체와 리스트 및 맵에 담긴 좌표 객체를 별 생각 없이 .equals()와 .containsKey() 메서드를 사용해 비교하고 있었음. 여기서 문제 발생

2. 문제 원인

.equals()메서드는 모든 필드가 서로 일치해도 두 객체를 같은 객체로 판단해 주지 않음!

public static void main(String[] args) {
	    TestObject objA = new TestObject(1,2,3);
	    TestObject objB = new TestObject(1,2,3);
	
	    System.out.println(objA.equals(objB));
}
false

또한 해시맵의 .containsKey()메서드 역시 모든 필드가 서로 일치하는 객체를 같다고 판단하지 않음

public static void main(String[] args) {
	    TestObject objA = new TestObject(1,2,3);
	
	    HashMap<TestObject, Integer> testMap = new HashMap<>();
	    testMap.put(objA, 1);
	
	    System.out.println(testMap.containsKey(new TestObject(1,2,3)));
}
false

3. 해결 방안

해시코드로 비교하기 → 실패

public static void main(String[] args) {
	    TestObject objA = new TestObject(1,2,3);
	    TestObject objB = new TestObject(1,2,3);
	
	    System.out.println(objA.hashCode());
	    System.out.println(objB.hashCode());
}
191382150
142666848

인텔리제이에서 alt+insert를 누르고 equals() and hashcode()를 선택하면 자동으로 해당 메서드들을 오버라이드 해줌!

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    TestObject that = (TestObject) o;
    return fieldA == that.fieldA && fieldB == that.fieldB && fieldC == that.fieldC;
}

@Override
public int hashCode() {
    return Objects.hash(fieldA, fieldB, fieldC);
}

이제 해당 TestObject 클래스의 인스턴스들은 필드들이 모두 일치할 경우 동일한 해시코드를 갖게 되며, equals()와 containsKey()메서드 또한 true를 반환함!

public static void main(String[] args) {
      TestObject objA = new TestObject(1,2,3);
      TestObject objB = new TestObject(1,2,3);
      HashMap<TestObject, Integer> testMap = new HashMap<>();
      testMap.put(objA,1);

      System.out.println(objA.hashCode());
      System.out.println(objB.hashCode());
      System.out.println(objA.equals(objB));
      System.out.println(testMap.containsKey(new TestObject(1,2,3)));
  }