为TEqualityComparer.Construct编写hasher函数的规范方法是什么?

时间:2012-07-02 13:27:29

标签: delphi hash delphi-xe2

考虑以下记录:

TMyRecord = record
  b: Boolean;
  // 3 bytes of padding in here with default record alignment settings
  i: Integer;
end;

我希望实施IEqualityComparer<TMyRecord>。为此,我想致电TEqualityComparer<TMyRecord>.Construct。这需要提供TEqualityComparison<TMyRecord>,这对我没有任何问题。

但是,Construct还需要THasher<TMyRecord>,我想知道实现它的规范方法。该函数需要具有以下形式:

function MyRecordHasher(const Value: TMyRecord): Integer;
begin
  Result := ???
end;

我希望我需要在记录值的两个字段上调用BobJenkinsHash,然后将它们组合起来。这是正确的方法,我该如何组合它们?

我不使用TEqualityComparison<TMyRecord>.Default的原因是它使用CompareMem,因此会因记录的填充而不正确。

1 个答案:

答案 0 :(得分:6)

关于覆盖hashCode的Effective Java (by Joshua Bloch)部分可能很有用。它显示了如何组合对象(或记录)的各个部分以有效地构造hashCode。

  

良好的散列函数往往会产生不等的哈希码   对象。这正是第三条规定的含义   hashCode合约。理想情况下,散列函数应该分配任何   合理地收集所有不平等的实例   可能的哈希值。实现这一理想可能非常困难。   幸运的是,实现公平的近似并不太难。这里   是一个简单的食谱:

     
      
  1. 将一些常量非零值(例如17)存储在名为int的{​​{1}}变量中。
  2.   
  3. 对于对象中的每个重要字段result(通过equals方法考虑的每个字段,即),请执行以下操作:

         

    一个。为字段计算f哈希码int:..... 详细信息省略 ....

         

    湾将步骤a中计算的哈希码c组合成   结果如下:c

  4.   
  5. 返回result = 37*result + c;

  6.   
  7. 完成result方法的编写后,请问自己,相等的实例是否具有相同的哈希码。如果没有,找出原因   并解决问题。

  8.   

这可以翻译成Delphi代码如下:

hashCode

这样就可以实现{$IFOPT Q+} {$DEFINE OverflowChecksEnabled} {$Q-} {$ENDIF} function CombinedHash(const Values: array of Integer): Integer; var Value: Integer; begin Result := 17; for Value in Values do begin Result := Result*37 + Value; end; end; {$IFDEF OverflowChecksEnabled} {$Q+} {$ENDIF}

MyRecordHasher