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

Dav*_*nan 5 delphi hash delphi-xe2

考虑以下记录:

TMyRecord = record
  b: Boolean;
  // 3 bytes of padding in here with default record alignment settings
  i: Integer;
end;
Run Code Online (Sandbox Code Playgroud)

我希望实施IEqualityComparer<TMyRecord>.为了做到这一点,我想打电话TEqualityComparer<TMyRecord>.Construct.这需要提供一个TEqualityComparison<TMyRecord>没有问题的我.

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

function MyRecordHasher(const Value: TMyRecord): Integer;
begin
  Result := ???
end;
Run Code Online (Sandbox Code Playgroud)

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

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

mjn*_*mjn 6

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

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

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

    一个.计算字段的int哈希码c:..... 详细信息省略 ....

    湾 将步骤a中计算的哈希码c合并到结果中,如下所示:result = 37*result + c;

  3. 返回result.

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

这可以转换成Delphi代码,如下所示:

{$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}
Run Code Online (Sandbox Code Playgroud)

然后允许执行MyRecordHasher:

function MyRecordHasher(const Value: TMyRecord): Integer;
begin
  Result := CombinedHash([IfThen(Value.b, 0, 1), Value.i]);
end;
Run Code Online (Sandbox Code Playgroud)