U8国际 U8国际官方网站 体育APP下载优化哈希策略Java开发Java经验技巧
栏目:U8体育 发布时间:2025-09-26
  u8,u8国际,u8国际官方网站,u8国际网站,u8国际网址,u8国际链接,u8体育,u8体育官网,u8体育网址,u8注册,u8体育网址,u8官方网站,u8体育APP,u8体育登录,u8体育入口   散列策略会对HashMap或HashSet之类的散列集合的性能产生直接的影响。   内置的散列(又称哈希

  u8,u8国际,u8国际官方网站,u8国际网站,u8国际网址,u8国际链接,u8体育,u8体育官网,u8体育网址,u8注册,u8体育网址,u8官方网站,u8体育APP,u8体育登录,u8体育入口

U8国际 U8国际官方网站 U8体育APP下载优化哈希策略Java开发Java经验技巧

  散列策略会对HashMap或HashSet之类的散列集合的性能产生直接的影响。

  内置的散列(又称哈希)函数都是通用的,在大多数使用情况下都能表现很好。但是

  在先前的一篇文章中,我研究了一些测试散列策略的方法,其中特别注意了一种“正交

  位”优化的散列策略,它仅仅只是改变一个位就能确保每个散列结果尽可能的不同。.

  然而,如果要对一•个已知的元素或关键字集合进行散列,你就可以针对具体案例进行

  一个散列集合中最主要的事情就是避免冲突了。所谓冲突,就是两个以上关键字映射

  到同一个散列槽中。这些冲突意味着当有多个关键字映射到同一个散列槽中时你必须

  要付出更多的努力来检查那些关键字是否是你想要的那个。理想状态下一个散列槽中

  通常的误解是只要散列码唯一-就可以避免冲突。虽然都希望散列码是唯-的,但它还不

  假设现在有一些关键字,每一个都有唯一的32位散列码。如果你有40亿散列槽,每个

  关键字都有自己的槽,那就没有冲突了。对于所有的散列集合,这样大的数组一般是

  不太现实的。事实上,HashMap和HashSet的大小都收到机器内存的限制,一般为

  当你只能有一个规模上比较实际的哈希集合时乂该如何呢?散列槽的数目需要更小一

  些,而散列码需对散列槽数目取模。如果散列槽数是2的蓦值,你可以用最低位当掩

  来看个例子,ftse350.csv。如果把第一列作为关键字或是元素,就有352个字符串。这

  些字符串有唯的StringO.hashCode()码,但是假设我们只取这些散列码的低位。会不会

  一个装载因子是0.7(默认)的HashMap的大小是512,使用哈希码的低九位作为掩码。可

  为了减少糟糕的散列策略造成的影响,HashMap使用了扰动函数。Java8里的实现相当

  下面是来自HashMap.hash的源码。想了解更多细节,可以阅读Javadoc文档。

  这个方法混合了原始哈希码的高位和低位,以此来提高低位的随机性。对于像上面的

  String的哈希实现已经在Javadoc中规定好了,所以我们基本没有机会改动,但我们可以

  ・代码结构。你需要一个无论选取什么样的魔法数字都能提供一个好的结果的代码结构。

  魔法数字固然很重要,但是你并不想让它过于重要;因为总是有些时候你选的数字并

  不适合你的使用场景。这就是为什么你同时还需要一个即使在魔法数字选取很糟糕的

  可以看到,魔法数的选取的确很重要,但需要尝试的数字太多了。我们需要写一个测

  可以发现,如果提供了好的乘数,或是适合于你的关键字集合的乘数,那么重复 乘上

  每个哈希值再加上下一个字符就很合理。对比分别以130795 和31 作乘数, 对于测试

  的关键字集合,前者只有81 次碰撞而后者有103 次。 如果你再加上扰动函数,碰撞会

  减少到大约68 次。这已经很接近加倍数组规模 时的冲突率了:不占用更多内存,却可

  但是当我们向散列集合中添加新的关键字时会发生什么呢?魔法数字还能表现 良好

  吗?这使我不得不研究最坏冲突率,以决定在面对更大范围的输入时,哪种 代码结构

  可能会表现得更好。hash。的最坏表现是250 次碰撞,即70%的关键字 发生冲突,确实

  很糟糕。扰动函数能稍稍提高性能,但作用也不大。注意:如果 我们选择与偏移值相

  然而,如果选择位移两次一一不仅仅是混合高低位,还有从产生的哈希值的四个 部分

  选择的位,结果发现,最坏情况的冲突率大大下降。这使我想到,在选择的 关键字改

  变的情况下,如果结构足够好,魔法数的影响足够低,我们得到糟糕结 果的可能性就

  最佳情况下的表现变好了 -些,然而最坏情况下的冲突率明显更高了。由此我看 出,魔

  法数选取的重要性提高了,也意味着,关键字的影响更大了。考虑到关键 字可能会随

  率相等;因为0*1=0, 1*1=1.然 而,如果与偶数相乘,最低位一定是0.也就是说,这一

  位不再是随机变化的了。 假设我们重复先前的测试,但是只采用偶数,结果会怎样?

  如果你很幸运,魔法数选对了,那么结果将会和奇数情况下一样好。然而如果不 太幸

  运,结果可能会很糟糕。325 次碰撞意味着,512 个哈希槽中只有27 个被使 用了。

  ・如果你的散列集合太大(比如百万以上),32 位的散列值很难保证唯-性。

  通过探索哈希值的产生过程,我们找到了将 352 个关键字的冲突次数从 103 次降 到 68

  次的方法。同时,我们也相信,如果关键字集合发生变化,我们也能降低 变化可能造

  作为对比,可以看到,加倍数组规模可以提高最佳情况下的表现。但我们仍然要 面对

  在你的关键字集合比较稳定的情况下,你可以通过调整哈希策略来明显改善冲突 率。

  当关键字集合改变时,你还需要测试不优化的情况下结果会糟糕到什么程度。 将这两

  种策略结合起来,你可以不占用更多内存和CPU就能得到提高性能的新哈 希策略。