Java 为什么散列函数不使用随机性?

Java 为什么散列函数不使用随机性?,java,algorithm,performance,Java,Algorithm,Performance,我在书中读到,好的散列函数是:h(x)=((a*x+b)mod p)mod m 其中a,brandom,pprime,m表格大小 我在任何编程语言的任何库中都找不到这个哈希函数,特别是在Java中。为什么? 我说的是哈希代码的实现。哈希不需要是随机的,它的目标是基于随机输入在有限范围内的可能结果中提供均匀分布。(假设您指的是“哈希表/哈希映射”中的“哈希”,而不是像SHA1这样的加密哈希) 现代散列设计的最佳实践实际上涉及随机性,以防止由输入所有散列值相同的输入的人造成的拒绝服务攻击,我相信Pe

我在书中读到,好的散列函数是:
h(x)=((a*x+b)mod p)mod m
其中
a,b
random,
p
prime,
m
表格大小

我在任何编程语言的任何库中都找不到这个哈希函数,特别是在Java中。为什么?
我说的是哈希代码的实现。

哈希不需要是随机的,它的目标是基于随机输入在有限范围内的可能结果中提供均匀分布。

(假设您指的是“哈希表/哈希映射”中的“哈希”,而不是像SHA1这样的加密哈希)


现代散列设计的最佳实践实际上涉及随机性,以防止由输入所有散列值相同的输入的人造成的拒绝服务攻击,我相信Perl的最新版本也能做到这一点;另请参见:

好的,两个答案都没有正确答案。jwodder谈到了用随机盐腌制散列,Juan则完全谈了别的事情

你提到的散列函数有随机a和b,但它只得到随机a和b一次。然后在数据的整个生命周期中使用相同的值。否则,您可能会遇到一个场景,同一个值有不同的散列,并且没有盐来区分它们为什么不同


您列出的哈希适合于根据哈希表的需要将值随机分布到存储桶中。但是,您在java中看到的哈希函数是加密函数,用于完整性和身份验证。或者,如果您实际上正在研究用于哈希表的代码,您可能会看到随机值a和b,但在那一点上它们只是常量,它们是在添加到库之前随机生成的。

在某些情况下,这可能是一个很好的哈希函数,但这将是一个糟糕的
哈希代码
实现。Java
hashCode
应该返回任意的
int
,因此通过
mod p
mod m
约束它是没有意义的

在像
java.util.HashMap
这样的哈希表中,表大小始终是2的幂,这允许使用按位AND,而不是缓慢的模计算。实际上,由于速度的原因,两个表的非幂几乎从未被使用过

在公式中使用任意的随机
a
b
肯定是错误的。使用
a==0
是一场全面的灾难,
a==p
a==m
也是如此。使用
a==0x8000000
只是稍微好一点,而且
a
还有许多其他非常糟糕的值


请注意,使用b`只是浪费时间,尤其是它没有添加哈希dos保护。虽然它使哈希值不可预测,但它保留了所有冲突。

您不能保证您的输入是随机的,我的意思是“未排序”。这不是一个要求。如果不需要随机性,为什么它会被包括在参考书中描述为“良好”的散列函数中?
h(x)=((a*x+b)mod p)mod m
,这似乎是一个函数,
h
的输入是
x
。我看不出它是如何以任何方式引用输出的。x是输入,h(x)是输出。x可以取任何值,但由于函数的最后一个“mod”m,h(x)将被限制在0和m之间。散列函数的思想是,给定x值的无序(随机)输入,它将为h(x)生成一组均匀分布的0到m值。“均匀分布”可以改为“随机分布”。谢谢,这意味着所有Java应用程序都可以被黑客攻击,因为它们没有抵御拒绝服务攻击的防御措施?@ipetr不,还有其他保护的可能性。你为什么说我说的是不同的东西?关于函数本身,a和b是两个常数,可以随机选择,也可以不随机选择。除了对java的澄清之外,你对其他单词也说了同样的话。你解释了散列函数的作用,而不是为什么公式中会有随机数。正如其他人提到的,我们不知道你是在谈论加密散列还是
散列码
的实现。后者不需要随机性。@LewBloch更新