Java HashMap put()实现.为什么不先检查参考文献?

Ace*_*oud 13 java standard-library

java.util.HashMap有一个put方法的实现,其中包含以下代码:

if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
    V oldValue = e.value;
    e.value = value;
    e.recordAccess(this);
    return oldValue;
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,为什么不首先进行引用检查(因为具有相同引用的两个对象将具有相同的哈希和equals())?

即是这样的:

if ((k = e.key) == key) {
    V oldValue = e.value;
    e.value = value;
    e.recordAccess(this);
    return oldValue;
} else if ( compare hash and equals) {
    // do something again with the value
}
Run Code Online (Sandbox Code Playgroud)

这不会节省比较吗?

jar*_*bjo 1

我不知道为什么,但 na\xc3\xafve 微基准测试表明,在 Oracle 的 VM(Intel、32 或 64 位)上,比较两个引用所需的时间大约是比较两个整数(如哈希码)的四倍。我本以为比较两个 32 位整数和两个地址指针在现代硬件上应该具有类似的运行时成本,但我可能只是没有考虑这里明显的事情。

\n\n

假设大多数情况下不同的密钥具有不同的哈希码,则比较密钥之前的哈希可以为每个不正确的密钥节省 75% 的运行时间,并为正确的密钥增加 25% 的运行时间。如果这确实节省了整体运行时间,当然取决于哈希映射表的确切内容和布局,但 Sun 工程师显然认为这种变体更适合大多数用途。

\n\n

用于基准测试的方法:

\n\n
public static int c1(int a, int b, int iter) {\n    int r = 0;\n    while((iter--)>0) {\n        if(a == b) {\n            r++;\n        }\n    }\n    return r;\n}\n\npublic static int c2(Object a, Object b, int iter) {\n    int r = 0;\n    while((iter--)>0) {\n        if(a == b) {\n            r++;\n        }\n    }\n    return r;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

  • 请显示更多代码。我认为这段代码在自动优化这段代码时已经非常可疑了。基准对于您忘记做的各种小事情非常非常敏感。例如:错误使用这些方法可能会导致您的方法根本不执行任何操作。我的意思是,实际上什么也没有。编译器可能会简单地优化您的整个方法调用。我不确定 JIT 是否会在超过阈值后优化比较。谁能证实这一点吗? (2认同)