散列字符串以在哈希表中使用(Double Hashing)

时间:2011-11-09 14:08:10

标签: java hash hashtable double-hashing

我正在尝试使用Double Hashing将String键散列到哈希表中。我做了类似的事情:

protected int getIndex(String key) {
  int itr = 0,
      size = this.values.length,
      index1,
      index2,
      index = 0;

  do {
    // do double hashing to get index for curr [itr] (iteration)
    index1 = Math.abs(key.hashCode()) % size;
    index2 = size - ((key + key + "#!@").hashCode() % size); # trying very hard to eliminate clash, but still fails ... TA and AT gets index 2 when size = 5
    index = (index1 + (itr * index2)) % size;

    // if itr > set threshold, exit
    itr++;
    if (itr > 200) {
      index = -1;
      break;
    }

    // once index found, exit loop
  } while (index > 0 && this.keys[index] != null && !this.keys[index].equals(key));

  return index;
}

主要部分是do之后的前3行。我可以说如果我使用Double Hashing,它应该消除碰撞的概率吗? size是哈希表的唯一键的总可能值

1 个答案:

答案 0 :(得分:2)

所以我看到这里发生了两件事

  1. 使用两个不同的哈希并将它们组合以尝试获得更分散的哈希值
  2. 如果哈希失败,请尝试新的点
  3. 乍一看,看起来这两种方法都是减少哈希冲突的好方法。然而,经过仔细检查,这两者都会陷入真正的算法麻烦。

    合并两个哈希
    散列算法被设计为在整数范围内相当好地分布。就像将两个随机数加在一起并没有给你任何更多的randomer一样,将两个哈希加在一起并不会让你获得更多的分布。事实上,将两个符号分布一起添加将总是给你一些不均匀分布的东西。因此,任何一种使用相同底层算法的双重哈希策略都比单个哈希策略更差。

    尝试新地点
    尝试在第一个碰撞时尝试新哈希的算法很有吸引力。但是,这会导致算法的检索部分出现问题。当你在哈希中放入一些东西时,它会碰到另一个位置。然后,当你去检索值时,它不在那里。更糟糕的是,你是否发现它取决于第一个元素是否仍然存在。如果它被删除了,那么就无法判断你正在寻找的项目是否还在继续,或者它是否就在那里。最终,一个.contains测试必须经过所有200次迭代才能确定它所寻找的哈希值不存在。

    最好的解决方案是使用Java提供的开箱即用哈希。如果你遇到很多冲突,最好在哈希中使用较低的加载因子。这会增加存储桶的数量,并导致冲突的可能性降低。