为TEqualityComparer.Construct写一个hasher函数的规范方法是什么? [英] What is the canonical way to write a hasher function for TEqualityComparer.Construct?

查看:115
本文介绍了为TEqualityComparer.Construct写一个hasher函数的规范方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下记录:

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> ,这对我没有任何问题。

I wish to implement IEqualityComparer<TMyRecord>. In order to do so I want to call TEqualityComparer<TMyRecord>.Construct. This needs to be supplied with a TEqualityComparison<TMyRecord> which presents no problems to me.

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

However, Construct also requires a THasher<TMyRecord> and I would like to know the canonical method for implementing that. The function needs to have the following form:

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

我希望我需要调用 BobJenkinsHash 在两个领域的记录价值,然后结合他们一些如何。这是正确的方法,应该如何组合?

I expect that I need to call BobJenkinsHash on both fields of the record value and then combine them some how. Is this the right approach, and how should I combine them?

我不使用 TEqualityComparison< TMyRecord> .Default 是使用 CompareMem ,因为记录的填充,所以将不正确。

The reason I don't use TEqualityComparison<TMyRecord>.Default is that it uses CompareMem and so will be incorrect due to the record's padding.

推荐答案

有效Java(作者为Joshua Bloch)关于覆盖hashCode的部分可能是有用的。它显示了如何将对象(或记录)的各个部分组合起来以有效地构建一个hashCode。

The Effective Java (by Joshua Bloch) section about overriding hashCode could be useful. It shows how the individual parts of the object (or record) can be combined to efficiently construct a hashCode.


一个好的哈希函数往往为不等的
对象产生不等的哈希码。这正是第三个条款的
hashCode合同的意思。理想情况下,哈希函数应该在所有
可能的哈希值中均匀分布任何
合理的不等式实例集合。实现这一理想是非常困难的。
幸运的是,实现公平的近似并不难。这里
是一个简单的配方:

A good hash function tends to produce unequal hash codes for unequal objects. This is exactly what is meant by the third provision of the hashCode contract. Ideally, a hash function should distribute any reasonable collection of unequal instances uniformly across all possible hash values. Achieving this ideal can be extremely difficult. Luckily it is not too difficult to achieve a fair approximation. Here is a simple recipe:


  1. 在$ code> int中存储一些常量非零值,如17 变量调用 result

  2. 对于每个重要字段 f 在对象(每个字段通过equals方法考虑在内),请执行以下操作:

  1. Store some constant nonzero value, say 17, in an int variable called result.
  2. For each significant field f in your object (each field taken into account by the equals method, that is), do the following:

a。计算一个 int 哈希代码 c 的字段:..... 细节省略 ....

a. Compute an int hash code c for the field: ..... details omitted ....

b。将步骤a中计算出的哈希码c与以下结果组合成
结果: result = 37 * result + c;

b. Combine the hash code c computed in step a into result as follows: result = 37*result + c;

返回结果

完成 hashCode 方法,询问自己是否相等的实例具有相等的哈希码。如果没有,找出为什么
并解决问题。

When you are done writing the hashCode method, ask yourself whether equal instances have equal hash codes. If not, figure out why and fix the problem.


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

This can be translated into Delphi code as follows:

{$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;

这篇关于为TEqualityComparer.Construct写一个hasher函数的规范方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆