자바 언어·플랫폼 용어 사전
컬렉션Arrays.hashCode · Arrays.equals

배열의 equals·hashCode

배열은 equals·hashCode를 재정의하지 않아 주소로 비교된다. 내용 비교는 Arrays.equals·Arrays.hashCode를 써야 한다.

배열은 객체이지만 Object 의 기본 구현을 그대로 쓴다. 그래서 내용이 같아도 다른 배열이다.

int[] a = {1, 2}, b = {1, 2};
a.equals(b);                                 // false — 주소 비교
a.hashCode() == b.hashCode();                // 거의 항상 false — 식별 해시
Arrays.equals(a, b);                         // true
Arrays.hashCode(a) == Arrays.hashCode(b);    // true

그래서 키로 쓰면 못 찾는다

Map<int[], String> map = new HashMap<>();
map.put(new int[]{1, 2}, "값");
map.get(new int[]{1, 2});      // null — 새 배열은 다른 해시

넣을 때 쓴 바로 그 배열 객체로만 찾을 수 있다. 사실상 쓸 수 없는 키다.

왜 재정의하지 않았나

배열은 언어가 직접 만드는 특수한 객체이고, 내용 비교를 기본으로 삼으면 모든 배열 비교가 O(n) 이 된다. 자바는 기본을 싸게 두고, 필요한 쪽이 Arrays 유틸을 부르도록 했다.

다차원은 한 겹 더

Arrays.equals(x, y)          // 1차원까지만 내용 비교
Arrays.deepEquals(x, y)      // 중첩 배열까지 재귀 비교
Arrays.deepHashCode(x)       // 마찬가지

int[][]Arrays.equals 로 비교하면 안쪽 배열들을 주소로 비교해 false 가 나온다.

대안

키가 필요하면 List<Integer>record 로 감싼다. 둘 다 내용 기반 계약을 갖는다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 컬렉션·예외·리소스