Javaハッシュコードの実装のどちらが優れているかについてのインタビューの質問と混同しています。クラス{point x、y;}があります。なぜこのクラスにハッシュコード31 * x + yを実装するのですか?はx + yより優れていますか?正解は「乗数はフィールドの処理順序にハッシュコード値の依存性を生み出し、最終的にはより良いハッシュ関数を生み出す」です。しかし、なぜ31 * x + yがpoint1.equals(point2);を実行すると計算全体が計算されるため、ここで処理がポイントになります。また、それが発生する順序は関係ありません。
Jean-BaptisteYunèsの答えは正しいですが、次の例を追加して説明します(これはjavascriptであることに注意してください。これは、この例にすばやく実装したためです)。
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
function getHashCollisions(collection, hashFunction) {
const collisionMap = new Map();
let count = 1;
let total = collection.length;
for (const point of collection) {
console.log(`calculating ${count++}/${total}`);
const currentHash = hashFunction(point);
const hashCount = collisionMap.has(currentHash) ? collisionMap.get(currentHash) +1 : 1;
collisionMap.set(currentHash, hashCount);
}
return collisionMap;
}
function generateDataset(rangeX, rangeY) {
const points = [];
let count = 1;
for (let x = 0; x < rangeX; x++) {
for (let y = 0; y < rangeY; y++) {
console.log(`generating ${count++} Point(${x};${y})`);
points.Push(new Point(x, y));
}
}
return points;
}
function calculateAndGenerateReport(dataset, hashFunction, hashFunctionName) {
const hashes = getHashCollisions(dataset, hashFunction);
const totalCollisions = Array.from(hashes.values()).filter(currentCollisionCount => currentCollisionCount > 1).length;
const highestCollisionCount = Array.from(hashes.values()).reduce((currentHighest, current) => current > currentHighest ? current : currentHighest) - 1;
return `${hashFunctionName}: ${totalCollisions} collisions, highest collision count: ${highestCollisionCount}`;
}
const dataset = generateDataset(100, 100);
const literalHashesReport = calculateAndGenerateReport(dataset, point => point.x + point.y, "literal hash function:");
const onePrimeHashesReport = calculateAndGenerateReport(dataset, point => 31 * point.x + point.y, "one prime multiplication hash function:");
const twoPrimesHashesReport = calculateAndGenerateReport(dataset, point => 31 * point.x + 37 * point.y, "two primes multiplication hash function:");
const twoLargePrimesHashesReport = calculateAndGenerateReport(dataset, point => 8191 * point.x + 131071 * point.y, "two large primes multiplication hash function:");
console.log(literalHashesReport);
console.log(onePrimeHashesReport);
console.log(twoPrimesHashesReport);
console.log(twoLargePrimesHashesReport)
結果:
literal hash function: 197 collisions, highest collision count: 99
one prime multiplication hash function: 3107 collisions, highest collision count: 3
two primes multiplication hash function: 3359 collisions, highest collision count: 2
two large primes multiplication hash function: 0 collisions, highest collision count: 0
これは、ハッシュを「計算」するために選択した(素数)数が衝突の確率を大幅に減少させることを示しています。