【问题标题】:The performance of the HashMap in JAVA8HashMap在JAVA8中的表现
【发布时间】:2017-07-15 05:37:33
【问题描述】:

在java8中学习HashMap源码的时候有个疑问。

源码这么复杂,效率多少?

于是我写了一段关于哈希冲突的代码。

public class Test {             
    final int i;            

    public Test(int i) {            
        this.i = i;     
    }           

    public static void main(String[] args) {            
        java.util.HashMap<Test, Test> set = new java.util.HashMap<Test, Test>();        
        long time;      
        Test last;      
        Random random = new Random(0);      
        int i = 0;      
        for (int max = 1; max < 200000; max <<= 1) {        
            long c1 = 0, c2 = 0;    
            int t = 0;  
            for (; i < max; i++, t++) { 
                last = new Test(random.nextInt());
                time = System.nanoTime();
                set.put(last, last);
                c1 += (System.nanoTime() - time);
                last = new Test(random.nextInt());
                time = System.nanoTime();
                set.get(last);
                c2 += (System.nanoTime() - time);
            }   
            System.out.format("%d\t%d\t%d\n", max, (c1 / t), (c2 / t)); 
        }       
    }           

    public int hashCode() {         
        return 0;       
    }           

    public boolean equals(Object obj) {         
        if (obj == null)        
            return false;   
        if (!(obj instanceof Test))     
            return false;   
        Test t = (Test) obj;        
        return t.i == this.i;       
    }           
}

我在 Excel 中显示结果。 enter image description here

我正在使用 java6u45 java7u80 java8u131。

不明白为什么java8的性能会这么差

我正在尝试编写自己的 HashMap。

想学java8的HashMap哪个更好,但是没找到。

【问题讨论】:

  • 因为返回单个静态值是一个可怕 hashCode() 实现。不要那样做。执行return Integer.hashCode(i);,您应该会看到更好的 性能。
  • @ElliottFrisch 我正在测试哈希冲突。
  • HashMap 的性能取决于您放入其中的键的hashCode() 方法的实现程度。如果你有一个糟糕的hashCode() 方法,不要指望它会表现良好。就像你有一个闪亮的新引擎,然后你往引擎里扔沙子并抱怨它的性能很差......
  • @Jesper 我只是比较java6 java7 java8 HashMap,而不是如何让HashMap更高效。我正​​在尝试编写自己的HashMap。我想在java8中学习HashMap,哪个更好,但是我没找到。
  • 您的基准测试看起来不正确 - 使用 jmh。另请参阅stackoverflow.com/questions/504103/…

标签: java java-8


【解决方案1】:

您的测试场景不适用于 Java 8 HashMap。 Java 8 中的HashMap 通过对任何长于给定阈值的哈希链使用二叉树来优化冲突。但是,这仅在密钥类型具有可比性时才有效。如果不是,那么测试是否可以进行优化的开销实际上会使 Java 8 HashMap 变慢。 (减速比我预期的要严重......但这是另一个话题。)

更改您的 Test 类以实现 Comparable&lt;Test&gt; ... 当哈希冲突的比例足够大时,您应该会看到 Java 8 的性能优于其他。


请注意,对于哈希函数不执行的情况,树优化应被视为一种防御措施。优化将O(N) 最坏情况性能变为O(logN) 最坏情况。

如果您希望您的 HashMap 实例具有 O(1) 查找,您应该确保您对密钥类型使用良好的哈希函数。如果碰撞概率最小化,那么优化就没有实际意义了。


源码这么复杂,效率多少?

在源代码中的cmets中有说明。可能还有其他 Google 可以为您找到的地方 :-)

【讨论】:

  • HashMap中的二叉树也是比较hash值。为什么不使用 2-choice 散列?
  • HashMap (Java 8) 中的二叉树不使用哈希值。它比较实际的键。请再次阅读代码。
  • @Stephen C:其实OP是对的,二叉树确实使用hashcode,就是为了解决bucket冲突。只有在真正的哈希冲突的情况下,它才会尝试使用可比较的密钥,然后使用身份哈希码。而且我还问自己,为什么它不使用 2-choice hashing 或类似的东西,但是,在 OP 的情况下,无论如何都无济于事。
猜你喜欢
  • 2017-08-28
  • 1970-01-01
  • 2015-11-17
  • 2017-04-14
  • 2017-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多