更快的hashCode()替代?

时间:2016-02-07 14:40:47

标签: java

有没有办法让hashCode()更快?当然我理解这可能会导致更多的冲突,但我可以通过这种权衡取舍。

java有没有办法“获取对象的内存地址,就像C ++一样?

编辑:要明确:我明白hashCode()很快。我的目标是创建一个与某些C ++哈希函数一样快的哈希函数。

我将要散列的项目类型未知。

3 个答案:

答案 0 :(得分:4)

  

有没有办法让hashCode()更快?

是的,很多方法,但这取决于你的哈希值。

注意:内置的Object.hashCode()大约需要40 ns。

  

java是否有办法获取对象的内存地址,就像C ++一样?

是的,您可以使用Unsafe来执行此操作,但这是一个坏主意,因为对象的地址可能随时更改,使其无法作为哈希。

该程序触发重新计算Object.hashCode()。

注意:这非常hacky,可能无法在所有JVM或未来的JVM上运行。它仅用于教育目的。

public class HashCodePerf {
    static int keep;

    public static void main(String[] args) {
        Object o = new Object();
        int runs = 20_000_000;
        for (int t = 0; t < 5; t++) {
            long start = System.nanoTime();
            for (int i = 0; i < runs; i++) {
                UNSAFE.putInt(o, 1L, 0); // reset the memory which stores the hashCode
                keep = o.hashCode(); // compute a new hashCode
            }
            long time = System.nanoTime() - start;
            System.out.printf("Object.hashCode takes %,d ns on average%n", time / runs);
        }
    }

    static final Unsafe UNSAFE;

    static {
        try {
            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true);
            UNSAFE = (Unsafe) theUnsafe.get(null);
        } catch (Exception e) {
            throw new AssertionError(e);
        }
    }
}

在我的超级书上打印

Object.hashCode takes 79 ns on average
Object.hashCode takes 43 ns on average
Object.hashCode takes 48 ns on average
Object.hashCode takes 43 ns on average
Object.hashCode takes 42 ns on average

创建一个非常简单的哈希,它将添加到计数器。

static int keep, keep2;
static int counter;

public static void main(String[] args) {
    Object o = new Object();
    Object o2 = new Object();
    int runs = 100_000_000;
    for (int t = 0; t < 5; t++) {
        long start = System.nanoTime();
        for (int i = 0; i < runs; i+=2) {
            UNSAFE.putOrderedInt(o, 1L, (counter += 0x5bc80bad) & 0x7FFFFFFF);
            UNSAFE.putOrderedInt(o2, 1L, (counter += 0x5bc80bad) & 0x7FFFFFFF);
            keep = o.hashCode(); // reload the hashCode
            keep2 = o2.hashCode(); // reload the hashCode
        }
        long time = System.nanoTime() - start;
        System.out.printf("Object.hashCode takes %,d ns on average%n", time / runs);
    }
}

打印

Object.hashCode takes 5 ns on average
Object.hashCode takes 8 ns on average
Object.hashCode takes 5 ns on average
Object.hashCode takes 4 ns on average
Object.hashCode takes 4 ns on average

注意:通常对象的地址会发生变化,但它的hashCode不会发生变化。在这种情况下,我们使用更改hashCode但具有相同地址的对象。

答案 1 :(得分:1)

  

有没有办法让hashCode()更快?当然我理解这可能会导致更多的冲突,但我可以通过这种权衡取舍。

这个特定问题的最佳答案是:

public int hashCode() {
     return 0;
}

任何Object都是正确的,它的速度和它一样快,它会为你提供大量的碰撞,你可以使用它。

答案 2 :(得分:0)

如果你想要与对象的地址类似的东西,你可以使用:

System.identityHashCode(obj);

如果多次调用hascode方法,你也可以缓存/预先计算结果(假设对象是不可变的,或者至少在构造之后它的hashcode不会改变)。

class CashHashcode {
  private final int hash;
  CacheHashcode(...) {
    hash = computeHashFromArgs(...);
  }
  public int hashCode() { return hash; }
}