如何在 Java 中深度复制哈希

How to deep copy a hasher in Java

我想散列 Java 中的大量 int[]。我的数组包含从根到树中节点的路径(节点已编号),因此它们在第一个值上非常相似(因为所有路径都来自根)。

我正在使用 Google Guava Hasher,我将数组的每个值添加到哈希器中以获取哈希码:

HashFunction hashFunction = Hashing.murmur3_128();
Hasher hasher = hashFunction.newHasher();
for (int i: myArray) {
    hasher.putInt(i);
}
int hashCode = inthasher.hash().asInt();

我想避免为每条路径再次对整个数组进行哈希处理,并且只通过将最后一个值添加到我的哈希器副本来对最后一个值进行哈希处理。像这样:

anotherHasher = hasher.clone();
anotherHasher.putInt(someInt);
int hashCode = hasher.hash().asInt();
int anotherHashCode = anotherHasher.hash().asInt();

但是Hasher没有克隆方法。

这种复制会节省计算时间吗?是否可以使用包含 Hasher 的包装器实现 Cloneable,即使后者不可克隆?如果是如何?还有别的办法吗?

编辑: 根据记录,使用 Guava 进行散列运算需要花费时间的不是添加带有 hasher.putInt(someInt) 的元素,而是散列运算本身在最后用 [=18 调用=].所以即使深度复制很快(但不是,请参阅 Tomasz Linkowski 的回答),我的方法不相关,不值得进一步研究。

这可以借助执行 deep copy of an object (here are some deep copy library recommendations) 的库来完成。

一个这样的库是 Kryo,可以通过以下方式实现:

  1. 实例化Kryo(注意这个对象的创建非常昂贵+它不是线程安全的):

    Kryo kryo = new Kryo();
    kryo.setInstantiatorStrategy(new StdInstantiatorStrategy());
    
  2. 正在调用 Kryo.copy(T):

    Hasher anotherHasher = kryo.copy(hasher)
    

但是,请注意,这可能不会比散列两次更快,因为:

  • Kryo 的 StdInstantiatorStrategy 使用 Objenesis 实例化 Hasher 实现(我不知道它有多快);
  • 和推荐的 DefaultInstantiatorStrategy 无法使用,因为 Hasher 实现没有无参数构造函数(有关更多详细信息,请参阅 Kryo 的 readme about InstantiatorStrategy)。

我建议使用 Java Microbenchmark Harness 对此进行基准测试(注意链接页面末尾的各种 JMH 插件)。