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

为什么String的hashCode()不缓存0?

万俟招
2023-03-14
问题内容

我在Java 6的String源代码中注意到,hashCode仅缓存除0以外的值。以下代码段显示了性能差异:

public class Main{
   static void test(String s) {
      long start = System.currentTimeMillis();
      for (int i = 0; i < 10000000; i++) {
         s.hashCode();
      }
      System.out.format("Took %d ms.%n", System.currentTimeMillis() - start);
   }
   public static void main(String[] args) {
      String z = "Allocator redistricts; strict allocator redistricts strictly.";
      test(z);
      test(z.toUpperCase());
   }
}

在ideone.com中运行此命令可获得以下输出:

Took 1470 ms.
Took 58 ms.

所以我的问题是:

  • 为什么String的hashCode()不缓存0?
  • Java字符串哈希为0的概率是多少?
  • 避免对于每次哈希值都为0的字符串每次都重新计算哈希值的性能损失的最佳方法是什么?
  • 这是缓存值的最佳实践方法吗?(即除了一个缓存所有?)

为了您的娱乐,这里的每一行都是一个散列为0的字符串:

pollinating sandboxes
amusement & hemophilias
schoolworks = perversive
electrolysissweeteners.net
constitutionalunstableness.net
grinnerslaphappier.org
BLEACHINGFEMININELY.NET
WWW.BUMRACEGOERS.ORG
WWW.RACCOONPRUDENTIALS.NET
Microcomputers: the unredeemed lollipop...
Incentively, my dear, I don't tessellate a derangement.
A person who never yodelled an apology, never preened vocalizing transsexuals.

问题答案:

您不用担心。这是考虑此问题的一种方法

假设您有一个应用程序什么都不做,只是整年都在哈希字符串周围。假设它需要全部存储在内存中的一千个字符串,以循环方式在它们上反复调用hashCode(),经过一百万次,然后再获取一千个新字符串,然后再次执行。

并假设字符串的哈希码为零的可能性实际上远大于1/2 ^ 32。我敢肯定,这是 有点 更大的1/2 ^ 32,但让我们说这是比差很多,像1 / ^
16(平方根!现在这是一个差很多!)。

在这种情况下,与其他任何人相比,Oracle工程师在改进这些字符串的哈希码的缓存方式方面将受益更多。因此,您给他们写信并要求他们修复它。他们发挥了魔力,因此只要s.hashCode()为零,它就会
立即 返回(甚至是第一次!100%的改善!)。可以说,在任何其他情况下,他们这样做都不会降低性能。

万岁!现在您的应用程序…让我们看看…快0.0015%!

过去需要花费一整天的时间现在只需23小时,57分钟和48秒!

并且请记住,我们设置了场景以使怀疑的所有可能好处,通常到了可笑的程度。

这对您来说值得吗?

编辑:
自从几个小时前发布此消息以来,我让我的一个处理器疯狂运行以寻找具有零哈希码的两个单词的短语。到目前为止,它提出了:甲壳动物zorillo,计时码表schtoff,挫伤性的回廊状,creashaks的有机杂志,鼓木巨石头,可进行电分析的且难以理解的。这是在大约2
^
35的可能性中进行的,因此,理想的分布情况下,我们希望只能看到8。显然,到完成时,我们的数量将是原来的几倍,但不会更多。更重要的是,我现在提出了一些有趣的乐队名称/专辑名称!没有公平的偷窃!



 类似资料:
  • 问题内容: 在OpenJDK中,该方法为: Javadoc说: 返回表示指定double值的Double实例。如果不需要新的Double实例,则通常应优先于构造方法Double(double)使用此方法,因为此方法通过缓存经常请求的值可能会产生明显更好的空间和时间性能。 这是实际的代码: 缓存是骗人的!这里发生了什么? 问题答案: 该方法存在多种类型:,和其他类型,并且文档始终相同:在某些情况下(

  • 本文向大家介绍String 为什 么是不可变的?相关面试题,主要包含被问及String 为什 么是不可变的?时的应答技巧和注意事项,需要的朋友参考一下 简单的来说:String 类中使用 final 关键字修饰字符数组来保存字符串,`private final char value[]`,所以 String 对象是不可变的。而StringBuilder 与 StringBuffer 都继承自 Ab

  • 我有以下Nginx配置,我们可以从的输出中看到,它在语法上是正确的。我在下面的输出中加粗了一些相关部分: 我知道在正常实践中,服务器和代理服务器在不同的主机上。目前,我只是试图学习如何配置Nginx代理服务器与内容缓存,因为Nginx对我来说是新的。 我有以下2MB随机字节文件: 当我卷曲反向代理服务器时,我得到一个200的响应: 但是,我的缓存目录为空: 我检查了和,没有记录错误。 在向反向代理

  • 本文向大家介绍为什么要用 redis ?为什么要用缓存?相关面试题,主要包含被问及为什么要用 redis ?为什么要用缓存?时的应答技巧和注意事项,需要的朋友参考一下 主要从“高性能”和“高并发”这两点来看待这个问题。 高性能: 假如用户第一次访问数据库中的某些数据。这个过程会比较慢,因为是从硬盘上读取的。将该用户访问的数据存在缓存中,这样下一次再访问这些数据的时候就可以直接从缓存中获取了。操作缓

  • 问题内容: Sun的规范JVM实现对字节码进行了一些相当复杂的优化,以在代码运行几次后获得接近本机的执行速度。 问题是,为什么没有将此编译后的代码缓存到磁盘以供以后使用同一功能/类时使用? 就目前而言,每次执行程序时,JIT编译器都会重新启动,而不是使用代码的预编译版本。当本质上解释字节码时,是否添加此功能不会大大提高程序的初始运行时间? 问题答案: 我不求助于@MYYN发布的链接的’n’past

  • 不管我怎么努力,页面都被缓存了。因此,php函数运行一次后,总是显示缓存的结果,直到您按下Shift F5 > 我禁用了奥普卡什(在 phpinfo()上不再有奥普卡切了) 我禁用了APC(phpinfo()上不再有APC) 我使用了标题 Cache-Control:no-store,no-cache,必须重新验证"); // HTTP/1.1标头(Cache-Control:post-check