JDK 8的新策略是处理hashmap碰撞(树而不是列表)的新策略,仅对于那些无法编写良好hashcode()的人



在Java 8中,HashMap替换为二进制树时的链接列表 桶中的元素数量达到一定的阈值

Q:提到的改进不过是关心那些不知道如何编写适当的hashcode((方法的程序员?还是在其他情况下有用?在哪些情况下,不可能编写良好的HashCode((方法?换一种情况

http://hg.openjdk.java.net/jdk8u/jdk8u/jdk8u/jdk8u/jdk/jdk/file/a006fa0a9e8f/src/src/src/share/share/share/classes/java/java/java/java/java/java/java/hashmap.java一下P>

当钥匙具有独特的哈希或有序时,在提供最坏情况的O(log n(操作时,值得添加的树箱的复杂性,因此,在偶然或恶意用法下,性能优雅地降低了hashcode((方法返回值,分布较差,以及许多键共享主题的钥匙,只要它们也很可比。

这种改进阻止了对手故意选择将落入同一桶的价值的服务攻击。不可能编写对此弹性的弹性,这在JVM实例之间也是稳定的。

如果您在哈希图中添加了足够的条目,则统计学上您将获得水桶碰撞。请注意,水桶碰撞不是不是与标签碰撞相同的东西。虽然HashCode碰撞总是会导致水桶碰撞,但任何2个hashcodes都有 1 / buccet count 击中同一桶的机会。

如果通过厄运(许多不同的钥匙碰巧插入了同一桶中(或糟糕的编码(选择不良的算法会为不同的键生成相同的哈希尺寸(,桶中的键数量较大,是检索的时间复杂性 o(n(,但现在为o(log n(。

认为,它不一定是"编码不好"的 hashcode算法。可能是您正在使用第三方库中的对象作为密钥,因此此更改也可以保护您免受他人的不良代码。

在哪种情况下不可能编写良好的hashcode((方法?

好吧,除了某人可能试图通过工程哈希碰撞来解决您的用例之外...

在某些情况下,完全基于价值的主题计算过于昂贵,因此您实现了"便宜而开朗的"版本。但是此版本有一些边缘情况。

一个示例是您将包装器用于大型数组或哈希图树作为钥匙的地方。(显然,这种方法有问题,但是有些人会这样做。(

您的主题可能不会像您认为它在HashMap中那样解释。例如,当您创建HashMap时,例如:

Map<String, String> map = new HashMap<>();

您至少应该知道3件事:

  • 仅考虑最后4位才能确定将要进行哪个桶条目。

  • HashMap will re-hash 通过:

    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }
    
  • HashCode是int,它是有限的,因此哈希碰撞经常。Integer.MAX_VALUE哈希碰撞的IIRC将开始大约数万(44_000?或类似的东西,不记得(。

最新更新