这是生成哈希码的好方法吗?

时间:2011-07-08 13:39:56

标签: java hash-code-uniqueness

我必须在以下两个条件下编写一个哈希函数:

  • 我对传递给方法的Object o一无所知 - 它可以是String,Integer或实际的自定义对象;
  • 我根本无法致电hashCode()

我正在使用的方法,计算哈希码:

  1. 将对象写入字节流;
  2. 将字节流转换为字节数组;
  3. 循环遍历字节数组并通过执行以下操作来计算哈希:

    hash = hash * PRIME + byteArray [i]

  4. 我的问题是它是一种可行的方法,有没有办法改善它?就个人而言,我觉得这个功能的范围太广了 - 没有关于对象是什么的信息,但在这种情况下我几乎没有发言权。

5 个答案:

答案 0 :(得分:3)

您可以使用HashCodeBuilder.reflectionHashCode而不是实施自己的解决方案。

答案 1 :(得分:1)

序列化方法仅适用于实际上可序列化的对象。因此,对于所有类型的对象实际上是不可能的。

此外,这会比较的对象具有等效的对象图,这与等于.equals() 不一定相同。

例如,由相同代码(具有相同数据)创建的StringBuilder对象将具有相等的OOS输出(即也等于散列),而b1.equals(b2)为假,并且具有相同元素的ArrayList和LinkedList将是注册为不同,list1.equals(list2)true


您可以通过创建自定义HashOutputStream来避免将字节流转换为数组步骤,该自定义class HashOutputStream extends OutputStream { private static final int PRIME = 13; private int hash; // all the other write methods delegate to this one public void write(int b) { this.hash = this.hash * PRIME + b; } public int getHash() { return hash; } } 只是获取字节数据并对其进行哈希处理,而不是将其保存为数组以供以后迭代

y = y*13 + x

然后将ObjectOutputStream包装在此类的对象周围。

您可以查看其他校验和算法,而不是Adler32方法。例如,java.util.zip包含zlib(以CRC32格式使用)和gzip(以{{1}}格式使用)。

答案 2 :(得分:0)

hash =(hash * PRIME + byteArray [i])%MODULO?

答案 3 :(得分:0)

此外,当你遇到它时,如果你想尽可能避免冲突,你可以在步骤3中使用标准化(加密,如果有意碰撞是一个问题)哈希函数,就像SHA-2一样?

看一下DigestInputStream,这也让你不用第2步。

答案 4 :(得分:0)

在非加密散列上查看Bob Jenkin's article。他介绍了一些方法,并讨论了它们在速度和碰撞概率之间的优势,劣势和权衡。

如果不出意外,它将允许您证明您的算法决策是正确的。向你的导师解释为什么你选择速度超过正确性,反之亦然。

作为起点,试试他的One-at-a-time hash

ub4 one_at_a_time(char *key, ub4 len)
{
  ub4   hash, i;
  for (hash=0, i=0; i<len; ++i)
  {
    hash += key[i];
    hash += (hash << 10);
    hash ^= (hash >> 6);
  }
  hash += (hash << 3);
  hash ^= (hash >> 11);
  hash += (hash << 15);
  return (hash & mask);
} 

这很简单,但对于更复杂的算法却非常出色。