Hash 两个哈希表大小与素数大小的幂

Hash 两个哈希表大小与素数大小的幂,hash,hashmap,hashtable,hashset,Hash,Hashmap,Hashtable,Hashset,使用两个哈希表大小的幂,而不是传统上使用的素数大小,有什么陷阱?使用素数可以保证修复原始散列函数的缺陷(例如,xoring键字节)还是仅仅是一个“散弹枪调试”?有什么更简单的哈希函数可以使用两个表大小的幂而不会将键聚集得太近?哈希函数返回的数字可能大于存储桶数组的大小。如果表大小为素数,则使用%(模数)获取实际存储桶,而如果表大小为2的幂,则使用位掩蔽,其速度远快于除法。掩蔽的问题是,如果哈希函数很差(即,如果它不能很好地分配低位),可能会有很多冲突。但是调整大小非常简单(只需将桶的数量增加一倍

使用两个哈希表大小的幂,而不是传统上使用的素数大小,有什么陷阱?使用素数可以保证修复原始散列函数的缺陷(例如,xoring键字节)还是仅仅是一个“散弹枪调试”?有什么更简单的哈希函数可以使用两个表大小的幂而不会将键聚集得太近?

哈希函数返回的数字可能大于存储桶数组的大小。如果表大小为素数,则使用
%
(模数)获取实际存储桶,而如果表大小为2的幂,则使用位掩蔽,其速度远快于除法。掩蔽的问题是,如果哈希函数很差(即,如果它不能很好地分配低位),可能会有很多冲突。但是调整大小非常简单(只需将桶的数量增加一倍)。另一方面,使用
%
总是需要一个素数的存储桶,所以将存储桶数加倍并不能回答您的问题吗@不幸的是,Java answer没有提供任何链接到讨论这个问题的论文,或者为什么素数可以工作。所以我应该确保高位和低位被置换?但这听起来比
%
更昂贵-要排列32位值位,每个字节至少需要四次表查找-即使是这样,也不能保证任何单个排列都能使用特定的键集(即,在调整表大小期间,需要自适应地选择排列)。是否有任何x86操作码来进行位置换?不,您不必置换任何位。你只需要一个好的散列函数,仅此而已。散列函数必须很好地分配低位,就像分配高位一样,这就是我的观点。为什么排列需要4个表查找?我不喜欢那些排列的东西,我相信你想得太多了。关于
%
需要素数的问题,这是因为除以非素数产生的提示比除以素数产生的提示冲突要大得多(这是数学,我现在不记得证明了,但它相当容易),因为
tbl1[dwbyte1]+tbl2[dwbyte2]+tbl3[dwbyte3]+tbl4[dwbyte4]
和大于8bit的表会给缓存带来太大的压力。当然,可以在执行字符串哈希时应用这些表,但这意味着要逐字节进行哈希。仍然不知道如何以比逐字节更快的速度散列c字符串。C/C++需要更好的基字符串类型。哈希函数返回的数字可能大于bucket数组的大小。如果表大小为素数,则使用
%
(模数)获取实际存储桶,而如果表大小为2的幂,则使用位掩蔽,其速度远快于除法。掩蔽的问题是,如果哈希函数很差(即,如果它不能很好地分配低位),可能会有很多冲突。但是调整大小非常简单(只需将桶的数量增加一倍)。另一方面,使用
%
总是需要一个素数的存储桶,所以将存储桶数加倍并不能回答您的问题吗@不幸的是,Java answer没有提供任何链接到讨论这个问题的论文,或者为什么素数可以工作。所以我应该确保高位和低位被置换?但这听起来比
%
更昂贵-要排列32位值位,每个字节至少需要四次表查找-即使是这样,也不能保证任何单个排列都能使用特定的键集(即,在调整表大小期间,需要自适应地选择排列)。是否有任何x86操作码来进行位置换?不,您不必置换任何位。你只需要一个好的散列函数,仅此而已。散列函数必须很好地分配低位,就像分配高位一样,这就是我的观点。为什么排列需要4个表查找?我不喜欢那些排列的东西,我相信你想得太多了。关于
%
需要素数的问题,这是因为除以非素数产生的提示比除以素数产生的提示冲突要大得多(这是数学,我现在不记得证明了,但它相当容易),因为
tbl1[dwbyte1]+tbl2[dwbyte2]+tbl3[dwbyte3]+tbl4[dwbyte4]
和大于8bit的表会给缓存带来太大的压力。当然,可以在执行字符串哈希时应用这些表,但这意味着要逐字节进行哈希。仍然不知道如何以比逐字节更快的速度散列c字符串。C/C++需要更好的基本字符串类型。