考虑以下记录:

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,因此由于记录的填充而将是不正确的。

最佳答案

有关覆盖hashCode的Effective Java (by Joshua Bloch)部分可能会很有用。它显示了如何组合对象(或记录)的各个部分以有效地构造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}

然后,这可以实现MyRecordHasher:
function MyRecordHasher(const Value: TMyRecord): Integer;
begin
  Result := CombinedHash([IfThen(Value.b, 0, 1), Value.i]);
end;

关于delphi - 为TEqualityComparer.Construct编写哈希函数的规范方法是什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11294686/

10-10 11:36