Java中的快速哈希表

时间:2013-01-09 02:16:50

标签: java arraylist hashtable chess

我正在创建一个国际象棋程序,它利用先前评估位置的哈希表来(希望)减少搜索时间。唯一的问题是我使用ArrayList来存储哈希值,并且查找时间会根据我存储的位置而增加。如何获得具有独立于当前大小的查找时间的哈希表? (原谅我,我有点像java的菜鸟,客观的c确实是我的事)

编辑:如果重要,我正在使用Zobrist快速散列技术。基于一些试验,我已经确定它不是占用大量时间的哈希键的生成。散列方法非常快,它对速度的影响几乎不明显。

3 个答案:

答案 0 :(得分:5)

标准的Java HashMap非常好并且已经可以使用了,但是如果你想在Java中使用惊人的最快地图,可以使用Trove(http://trove4j.sourceforge.net/html/overview.html),它充满了针对性能进行了优化的数据结构。

答案 1 :(得分:4)

首先是一个初步说明:在国际象棋行话中,术语transposition table比“哈希表”更常见,并且会在Google上为您提供更好的搜索结果。

考虑到这一点,转置表和通用哈希表(例如,Java Map)之间存在重要差异:

映射是一个关联数组,可确保在插入新值时不删除任​​何现有条目。通常,这是你想要的,但是当你写一个国际象棋引擎时,如果你不删除或覆盖旧条目,你很快就会耗尽内存。

相比之下,转置表更像是一个缓存,它只包含最新的条目。它可以实现为一个简单的固定大小数组,由当前位置的哈希值寻址。计算密钥的一种众所周知且非常有效的方法是Zobrist hashing(您在问题中已经提到过)。此键用于索引数组。添加新条目时,它们只会覆盖现有条目。

这是一些伪代码来说明这个想法:

// the transposition table entry
class TTEntry {
  long hashKey; // should be at least 64-bit to be safe

  // other information, e.g.:
  Move move;
  int distance;
  // ...
}

TTEntry[] ttable = ... // the more memory, the better

Entry getTTEntry(Board board) {
  long hashKey = board.getHashKey();
  int index = hashKey % ttable.length;
  return ttable[index];
}

void store(Board board) {
  Entry entry = getTTEntry(board);
  entry.hashKey = board.getHashKey();
  entry.move = ...;
  entry.distance = ...;
}

void probe(Board board) {
  Entry entry = getTTEntry(board);
  if (entry.hashKey == hashKey) {
    // entry found
    // ... do something with entry.move and entry.distance
  }
}

您说您使用的是ArrayList,但您的查询时间随着存储位置的数量而增加。如果您使用上面示例中的技术,则永远不会发生这种情况。它不仅与搜索位置的数量无关,而且还会比HashMap更快,而内部则更复杂。

答案 2 :(得分:2)

java.util.HashMap是您最好的选择。密钥查找是O(1)(摊销),它是一个非常好的通用HashMap。

这并不是说它是最优的:如果你知道如何并且有很多时间/决心,你当然可以设计一个自定义的hashmap实现,以更好地适应你的特殊情况。但是常规的HashMap绝对是开始的地方 - 您可以随时优化。