Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 如何测试哈希函数?_Algorithm_Unit Testing_Language Agnostic_Testing_Hash - Fatal编程技术网

Algorithm 如何测试哈希函数?

Algorithm 如何测试哈希函数?,algorithm,unit-testing,language-agnostic,testing,hash,Algorithm,Unit Testing,Language Agnostic,Testing,Hash,有没有办法测试散列函数的质量?我希望在哈希表中使用时有一个良好的扩展,如果在单元测试中可以验证这一点,那就太好了 编辑:为了澄清,我的问题是我在Java中使用了long值,第一个32位编码了一个ID,第二个32位编码了另一个ID。不幸的是,Java的长值散列只是将第一个32位与第二个32位异或,在我的例子中,当在HashMap中使用时,这会导致非常差的性能。因此,我需要一个不同的哈希表,并希望进行单元测试,这样这个问题就不会再出现了。如果您使用的是链式哈希表,那么您真正关心的是冲突的数量。这对于

有没有办法测试散列函数的质量?我希望在哈希表中使用时有一个良好的扩展,如果在单元测试中可以验证这一点,那就太好了


编辑:为了澄清,我的问题是我在Java中使用了
long
值,第一个32位编码了一个ID,第二个32位编码了另一个ID。不幸的是,Java的长值散列只是将第一个32位与第二个32位异或,在我的例子中,当在
HashMap
中使用时,这会导致非常差的性能。因此,我需要一个不同的哈希表,并希望进行单元测试,这样这个问题就不会再出现了。

如果您使用的是链式哈希表,那么您真正关心的是冲突的数量。这对于在哈希表上实现为一个简单的计数器来说是微不足道的。每次插入一个项目并且表必须连锁时,增加一个连锁计数器。更好的散列算法将导致更少的冲突。一个好的通用表散列函数是:

首先,我想你必须定义好的散列是什么意思。你是说所有可能的输入都有一个好的排列,还是说可能的输入都有一个好的排列

例如,若要对表示正确完整(名字+姓氏)名称的字符串进行散列,那个么您可能不会关心数字ASCII字符是如何散列的

至于测试,您最好的选择可能是获取您期望的大量或随机输入数据集,并将其推送到散列函数中,然后查看排列结果。不可能有一个神奇的程序会说“是的,这是一个适合您的用例的好的哈希函数”。但是,如果您可以通过编程生成输入数据,那么您应该能够轻松创建生成大量数据的单元测试,然后验证排列是否在您定义的良好范围内


编辑:对于64位长的文件,是否真的有理由使用哈希映射?为什么不直接使用平衡树,直接使用long作为键,而不是对其进行重新灰化?您在总节点大小(键值大小的2倍)上付出了一点代价,但最终可能会将其保存在性能上。

您必须使用从您期望的相同(或类似)分布中提取的数据来测试哈希函数。当查看64位长的散列函数时,如果输入值是从所有可能的长值中统一提取的,那么默认的Java散列函数是非常好的

但是,您已经提到,您的应用程序使用long存储两个独立的32位值。尝试生成一个与您期望实际使用的值相似的值样本,然后用它进行测试

对于测试本身,获取示例输入值,对每个值进行散列,并将结果放入一个集合中。计算结果集的大小,并将其与输入集的大小进行比较,这将告诉您哈希函数正在生成的冲突数


对于您的特定应用程序,与其简单地将它们XOR在一起,不如尝试以一个典型的良好哈希函数组合两个独立整数的方式组合32位值。也就是说,乘以素数,然后根据您的说明进行相加。

我在Java中使用长值的方式是,第一个32位编码一个ID,第二个32位编码另一个ID。不幸的是,Java的长值散列只是将第一个32位与第二个32位进行异或,这在我的例子中导致在哈希映射中使用时性能非常差

在分配两个ID值的方式和HashMap实例的大小之间,似乎存在一些不愉快的“共振”

您是显式调整地图大小,还是使用默认值?QAD检查似乎表明
HashMap
以16个bucket结构开始,并在溢出时加倍。这意味着只有ID值的低阶位实际参与哈希桶选择。您可以尝试使用一个接受初始大小参数的构造函数来创建具有初始大小的贴图

另外,Dave L建议定义自己的长键散列,这样可以避免低位依赖性问题


另一种方法是使用原语类型(long)来避免定义真正的类。我建议您通过定义业务类,然后在您自己的类上实现哈希编码、相等和其他适当的方法来管理此问题,看看您可以实现哪些好处。

您认为如何在合理的时间内测试64位的密钥空间,并获得可靠的结果?我并没有真正使用整个64位空间,这足以生成一百万个左右的数字,我通常使用这些数字进行测试。使用集合的大小计算碰撞是一个好主意,谢谢!