有时,最好的了解方法是对您的靶场进行一些蛮力测试。但最终,您始终可以编写一个哈希函数,如果性能变差,可以稍后再进行修复。过早的优化是邪恶的。尽管如此,测试哈希还是很容易的。
我运行了该程序,发生了0次碰撞:
import java.util.HashMap;import java.util.Map;import java.util.Map.Entry;public class Testing { public static void main(String[] args) { int minX = 0; int minY = 100000; int maxX = 20; int maxY = 2000000; Map<Integer, Integer> hashToCounts = new HashMap<Integer, Integer>(); for (int x = minX; x < maxX; x++) { for (int y = minY; y < maxY; y++) { int hash = hash(x, y); Integer count = hashToCounts.get(hash); if (count == null) count = 0; hashToCounts.put(hash, ++count); } } int totalCollisions = 0; for (Entry<Integer, Integer> hashCountEntry : hashToCounts.entrySet()) if (hashCountEntry.getValue() > 1) totalCollisions += hashCountEntry.getValue() - 1; System.out.println("Total collisions: " + totalCollisions); } private static int hash(int x, int y) { return 7 + y * 31 + x * 23; }}
并输出:
总碰撞:0
请注意,我的功能是
7 + y * 31 + x * 23。
当然,不要相信我。混乱的范围调整到您的数据集,并尝试自己计算。
用你
(y * 31) ^ x给我的:
总碰撞:475000
并只使用
x * y:
碰撞总数:20439039
警告该程序可以使用相当大的内存和计算能力。我在功能强大的服务器上运行它。我不知道它将如何在本地计算机上运行。
遵循一些良好的哈希规则是:
- 混淆您的运营商。通过混合您的运算符,可以使结果变化更大。仅x * y在此测试中使用,我发生了很多碰撞。
避免使用移位运算符(除非您真的很清楚自己在做什么)。它们在数字的二进制数中插入大量零或一,从而降低了其他运算的波动性,甚至可能缩小您可能的输出数。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)