고유 한 키 페어 객체를 생성 할 때 몇 가지 문제에 직면해야합니다.
먼저 hashCode()
및 equals()
. 이 작업을 수행해야합니다.
둘째,를 구현할 때 hashCode()
작동 방식을 이해해야합니다. 주어진 사용자 예
public int hashCode() {
return this.x ^ this.y;
}
실제로 할 수있는 최악의 구현 중 하나입니다. 이유는 간단합니다. 동일한 해시가 많이 있습니다! 그리고는 hashCode()
희귀하고 고유 한 경향이있는 int 값을 반환해야합니다. 다음과 같이 사용하십시오.
public int hashCode() {
return (X << 16) + Y;
}
이것은 빠르며 -2 ^ 16에서 2 ^ 16-1 (-65536에서 65535) 사이의 키에 대해 고유 한 해시를 반환합니다. 이것은 거의 모든 경우에 적합합니다. 이 범위를 벗어나는 경우는 거의 없습니다.
셋째, 구현할 때 equals()
그것이 무엇을 위해 사용되는지 알고 키가 객체이기 때문에 키를 만드는 방법을 알고 있어야합니다. 진술로 인해 항상 동일한 결과를 얻을 수 있다면 종종 불필요합니다.
이와 같은 키를 생성하는 경우 : 키 map.put(new Key(x,y),V);
의 참조를 비교하지 않습니다. 지도에 액세스하고 싶을 때마다 map.get(new Key(x,y));
. 따라서 당신 equals()
은 같은 진술이 필요하지 않습니다 if (this == obj)
. 그것은 것입니다 결코 발생 시킬수 없습니다.
대신 if (getClass() != obj.getClass())
당신의 equals()
더 나은 사용 if (!(obj instanceof this))
. 하위 클래스에도 유효합니다.
따라서 비교해야하는 유일한 것은 실제로 X와 Y입니다. 따라서이 경우 가장 좋은 equals()
구현은 다음과 같습니다.
public boolean equals (final Object O) {
if (!(O instanceof Key)) return false;
if (((Key) O).X != X) return false;
if (((Key) O).Y != Y) return false;
return true;
}
따라서 결국 키 클래스는 다음과 같습니다.
public class Key {
public final int X;
public final int Y;
public Key(final int X, final int Y) {
this.X = X;
this.Y = Y;
}
public boolean equals (final Object O) {
if (!(O instanceof Key)) return false;
if (((Key) O).X != X) return false;
if (((Key) O).Y != Y) return false;
return true;
}
public int hashCode() {
return (X << 16) + Y;
}
}
차원 인덱스 X
와 Y
공개 액세스 수준은 최종 항목이고 민감한 정보를 포함하지 않기 때문에 제공 할 수 있습니다 . 나는 확실히 여부를 100 % 아니에요 private
액세스 수준이 제대로 작동 어떤 을 캐스팅 할 때 경우 Object
A를 Key
.
파이널에 대해 궁금하다면 인스턴스에 설정되고 절대 변경되지 않는 값을 final로 선언하므로 객체 상수입니다.