【问题标题】:Why is my HashMap implementation 10 times slower than the JDK's?为什么我的 HashMap 实现比 JDK 慢 10 倍?
【发布时间】:2015-10-19 11:48:07
【问题描述】:

我想知道有什么不同,我在编写代码时应该注意什么。

  • 测试时使用相同的参数和方法put()get() 无需打印
  • 使用System.NanoTime() 测试运行时
  • 我尝试使用具有 10 个值的 1-10 个 int 键,因此每个哈希都返回唯一索引,这是最佳方案
  • 我基于此的 HashSet 实现几乎和 JDK 一样快

这是我的简单实现:


public MyHashMap(int s) {

    this.TABLE_SIZE=s;
    table = new HashEntry[s];

}

class HashEntry {

    int key;
    String value;

    public HashEntry(int k, String v) {
        this.key=k;
        this.value=v;
    }

    public int getKey() {
        return key;
    }

}



int TABLE_SIZE;

HashEntry[] table;

public void put(int key, String value) {

    int hash = key % TABLE_SIZE;

    while(table[hash] != null && table[hash].getKey() != key)
        hash = (hash +1) % TABLE_SIZE;

        table[hash] = new HashEntry(key, value);
}


public String get(int key) {

    int hash = key % TABLE_SIZE;

        while(table[hash] != null && table[hash].key != key)
            hash = (hash+1) % TABLE_SIZE;

            if(table[hash] == null)
                return null;
            else
                return table[hash].value;

}

这是基准:

public static void main(String[] args) {


    long start = System.nanoTime();

    MyHashMap map = new MyHashMap(11);

    map.put(1,"A");
    map.put(2,"B");
    map.put(3,"C");
    map.put(4,"D");
    map.put(5,"E");
    map.put(6,"F");
    map.put(7,"G");
    map.put(8,"H");
    map.put(9,"I");
    map.put(10,"J");


    map.get(1);
    map.get(2);
    map.get(3);
    map.get(4);
    map.get(5);
    map.get(6);
    map.get(7);
    map.get(8);
    map.get(9);
    map.get(10);

    long end = System.nanoTime();

    System.out.println(end-start+" ns");


}

【问题讨论】:

  • 如果没有测试显示比较的另一面,即您使用HashMap,则该问题是不完整的。您还应该展示您的微基准,因为其中的小错误会完全扭曲结果。

标签: java performance hashmap runtime


【解决方案1】:

如果您是HashMap 类的read the documentation,您会看到它实现了基于键的hashCode 的哈希表实现。如果映射包含非平凡数量的条目,这比蛮力搜索要高效得多,假设在将条目分类到的“桶”中分配了合理的密钥。

也就是说,对 JVM 进行基准测试是 non-trivial and easy to get wrong,如果您发现少量条目存在很大差异,则很可能是基准测试错误而不是代码。

【讨论】:

  • hashCode 在这里无关紧要,因为 OP 正在尝试使用 int 键制作地图。
  • @PaulBoddington: hashCode 与我在其中使用的句子相关:“...它 [HashMap] 基于键的 hashCode 实现了一个哈希表。” 我不是在谈论那里的 OP 代码。
  • 我用以下方式重写了代码:我现在使用 2 个长度相同的数组,而不是使用 HashEntry 类型:int[] keysString[] values,并且执行速度比 JDK 更快。现在我很困惑。 @T.J.克劳德
【解决方案2】:

当取决于性能时,永远不要假设什么。

您的假设是“我的基于此的 HashSet 实现几乎与 JDK 一样快”。不,显然不是。

这是执行性能工作时最棘手的部分:怀疑一切,除非您的测量非常准确。更糟糕的是,您甚至进行了测量,而测量结果告诉您您的实施速度较慢;而不是检查您的来源,以及您正在衡量的事物的来源;你认为测量过程一定是错误的......

【讨论】:

  • 我知道我的代码很差,我想提高我的技能。
  • 我没这么说。我只是想让你知道“根据假设工作”是危险的。并且那个人真的必须让这种同步并不断质疑自己的心态。
猜你喜欢
  • 1970-01-01
  • 2019-04-05
  • 1970-01-01
  • 2014-02-09
  • 2014-11-04
  • 1970-01-01
  • 2022-01-22
  • 2015-10-07
  • 1970-01-01
相关资源
最近更新 更多