当前位置: 首页 > 面试题库 >

什么是hashCode计算的明智素数?

鲜于璞瑜
2023-03-14
问题内容

Eclipse 3.5具有一个非常好的功能,可以生成Java hashCode()函数。例如,它将生成(略微缩短:)

class HashTest {
    int i;
    int j;        
    public int hashCode() {
        final int prime = 31;
        int result = prime + i;
        result = prime * result + j;
        return result;
    }
}

(如果类中具有更多属性,result = prime * result + attribute.hashCode();则为每个其他属性重复此操作。对于ints,可以省略.hashCode()。)

这似乎很好,但是对于首选的31。它可能取自JavaString的hashCode实现,出于性能原因而使用该特性,在引入硬件乘法器之后就已经不复存在了。在这里,对于i和j的较小值,您会有很多哈希码冲突:例如(0,0)和(-1,31)具有相同的值。我认为这是Bad
Thing(TM),因为经常会出现小的值。对于String.hashCode,您还会发现许多具有相同哈希码的短字符串,例如“ Ca”和“
DB”。如果您要大的质数,那么选择质数权会消除此问题。

所以我的问题是:选择什么是最佳素数?您应用什么标准找到它?

这是一个一般性问题-
因此,我不想为i和j给出范围。但是我想在大多数应用程序中,相对较小的值比较大的值更经常出现。(如果值较大,则选择质数可能并不重要。)这可能并没有多大区别,但是更好的选择是改善此问题的简便而显而易见的方法-
那么为什么不这样做呢?Commons langHashCodeBuilder也建议使用很小的值。

澄清 :这 _不是_为什么Java中String的hashCode()使用31作为乘数)因为我的问题与JDK中31的历史无关,而是在新代码中什么更好的价值)使用相同的基本模板。那里的答案都无法尝试回答。)


问题答案:

我建议使用 92821 。这就是为什么。

要对此给出有意义的答案,您必须了解i和的可能值j。我唯一能想到的是,在许多情况下,小值比大值更常见。(在程序中显示为15的几率要比438281923好得多。)因此,通过选择适当的质数来使最小的哈希码冲突尽可能大似乎是一个好主意。对于31这个很坏的-已经为i=-1j=31你有相同的哈希值作为i=0j=0

由于这很有趣,因此我编写了一个小程序,在这个意义上,它在整个int范围内搜索最佳素数。也就是说,对于每个素数,我搜索与相同的哈希码的Math.abs(i)+Math.abs(j)所有值中的最小值,然后在该最小值尽可能大的地方取素数。i,j``0,0

Drumroll :从这个意义上说,最好的素数是486187739(最小的碰撞是i=-25486,j=67194)。92821碰撞最小,几乎一样容易记住i=-46272 and j=46016

如果给“小”赋予另一个含义,并希望将其作为最小Math.sqrt(i*i+j*j)碰撞的最大值,则结果会有所不同:最好是1322837333具有i=-6815and j=70091,但我最喜欢的92821(最小碰撞-46272,46016)仍然几乎一样好作为最佳价值。

我确实承认,这些计算在实践中是否有意义尚有争议。但我确实认为,除非有充分的理由,否则将92821作为质数比31更有意义。



 类似资料:
  • 问题内容: 我总是看到人们使用它来造成处理延迟或类似的事情,人们总是为使用这种方式而感到嘲笑。 什么时候明智/需要使用? 问题答案: 当您确实需要延迟后台线程时,应该致电。 不要调用它来帮助同步(不会),不要在循环中调用它来等待某些东西(这会很慢),也不要在UI线程上调用它(它会冻结)。

  • 根据这个答案,我需要做一些逐行计算 但在此之前,我需要按降序对行值进行排序(更改数据框中每行的列顺序?)假设我有以下行 例如,我需要知道每行每个值的排名(顺序),然后计算第一行的总和(值/索引) 第二排 不是重复的,因为我需要排序不是列,而是行

  • 计算机(computer)是能以人的几百万甚至几十亿倍速度进行计算并作出逻辑判断的设备。例如今天的许多个人计算机每秒钟可以进行几亿次加法运算。操作台式计算器的人要几十年才能算出的数值,强大的个人计算机只要一秒钟即可计算完毕(注意:你怎么知道这个人加对了没有?你怎么知道计算机做得是否正确?)。 如今最快的超级计算机(supercomputer)每秒钟可以进行几干亿次加法运算,是成百上千的人花一整年时

  • 问题内容: 我有一个go项目,这个项目开始变得越来越复杂,并且希望以减轻痛苦的方式布置文件系统。 是否有一些很好的例子说明什么有意义? 问题答案: 2013年5月更新:官方文档位于“ 代码组织 ”部分 Go代码必须保存在 工作空间中 。 工作区是目录层次结构,其根目录包含三个目录: 包含归类为软件包的Go源文件(每个目录一个软件包), 包含包对象,并且 包含可执行命令。 在构建源码包和安装产生的二

  • 问题内容: 如果没有覆盖该方法,默​​认的实现是什么? 问题答案: 然后,此类从其祖先之一继承。如果它们都不覆盖它,则使用Object.hashCode。 从文档: 在合理可行的范围内,由Object类定义的hashCode方法确实为不同的对象返回不同的整数。(通常通过将对象的内部地址转换为整数来实现,但是JavaTM编程语言不需要此实现技术。) 因此默认实现是特定于JVM的

  • 1.2 什么是计算思维? 如前所述,计算是利用计算机一步一步地执行指令来解决问题的过程,计算机科学是关于计算的科学。正如数学家在证明数学定理时有独特的数学思维、工程师在设计制造产品时 有独特的工程思维、艺术家在创作诗歌音乐绘画时有独特的艺术思维一样,计算机科学家在 用计算机解决问题时也有自己独特的思维方式和解决方法,我们统称之为 计算思维(computational thinking)。从问题的计