숫자 평면 좌표에 가장 클러스터링하는 경향이있다; 왜냐하면 편안한 범위 내에서 숫자를 사용하는 경향이 있기 때문입니다. 이러한 이유 때문에 사소한 xor 조합은 바람직하지 않습니다. x == y
이 충돌 할 모든 숫자와 마찬가지로 모든 숫자는 x + 1 == y
등입니다.
이러한 문제가 발생하지 않도록하기 위해, 나는 당신이 x 좌표를에 xor 전에 y 좌표의 바이트를 반대하는 것이 좋습니다. 이것은 한 입력의 가장 가변적 인 영역 (하위 바이트)과 다른 입력의 가장 작은 가변성 (상위 바이트)의 영역을 결합합니다. 이러한 알고리즘은 숫자 클러스터 (1에서 1000 사이의 x 값)를 고려할 때보다 균일 한 분포를 제공합니다.
해시 알고리즘은 무거운 클러스터링없이 숫자 필드를 생성 할 때 가장 잘 작동하므로 해시 충돌이 적어 해시 관련 데이터 구조가 더 빨라집니다. 다음
는
물론, 최적화되지이다, 그리고 확률은 아마 당신은 당신의 필요에 맞게 트리밍 할 수 있지만, 여기에 기본 생각이다 :
public int hashCode() {
long bits = Double.doubleToLongBits(y);
byte[] ybits = new byte[] {
(byte)((y >> 56) & 0xff),
(byte)((y >> 48) & 0xff),
(byte)((y >> 40) & 0xff),
(byte)((y >> 32) & 0xff),
(byte)((y >> 24) & 0xff),
(byte)((y >> 16) & 0xff),
(byte)((y >> 8) & 0xff),
(byte)((y >> 0) & 0xff),
};
byte[] xbits = new byte[] {
(byte)((x >> 56) & 0xff),
(byte)((x >> 48) & 0xff),
(byte)((x >> 40) & 0xff),
(byte)((x >> 32) & 0xff),
(byte)((x >> 24) & 0xff),
(byte)((x >> 16) & 0xff),
(byte)((x >> 8) & 0xff),
(byte)((x >> 0) & 0xff),
};
// this combines the bytes of X with the reversed order
// bytes of Y, and then packs both of those into 4 bytes
// because we need to return an int (4 bytes).
byte[] xorbits = new byte[] {
(xbits[0]^ybits[7])^(xbits[4]^ybits[3]),
(xbits[1]^ybits[6])^(xbits[5]^ybits[2]),
(xbits[2]^ybits[5])^(xbits[6]^ybits[1]),
(xbits[3]^ybits[4])^(xbits[7]^ybits[0]),
};
int value = 0;
for (int i = 0; i < 3; i++) {
value = (value << 8) + (by[i] & 0xff);
}
return value;
}
초기 최적화 나는를 캐시하는 것입니다 제안 후속 조회를 위해 오브젝트의 해시 코드를 작성하고, 프로파일 링이 문제가 있다고 제시하면 작성/삭제 된 어레이를보다 효율적으로 관리하십시오.
@Cam : 나는 그것이 중복이라고 생각하지 않는다.그 대답은 어떻게 든 기하학적으로 가까운 점에 대해 동일한 해시를 만드는 무언가를 찾고 있습니다. –
좋은 지적. 나는이 질문을 끝내기 위해 제 제안을 철회합니다. – Cam
@OliCharlesworth 저에게 설명해 주셔서 감사합니다. 오늘 나는 이미 2 ~ 3 개의 질문을 마쳤습니다. 이 사람이 살아남기를 바랍니다. : D –