delphi - TDictionary<TVehicle, TPerson> 的 Equals 和 GetHashCode

标签 delphi generics hashmap tdictionary

如果我在 Delphi 中使用 TDictionary 实现关系 Car <-> Owner,我应该如何实现 IEqualityComparer 的 Equals 和 GetHashCode 函数? (GetHashCode 返回一个 Integer,用于 TDictionary 中的散列。)

对于 TVehicle 类,假设它具有 VIN(车辆识别号)。

我应该如何实现 VIN 的哈希码?

更新:在这个例子中,对象标识并不意味着“两个对象指针的内存位置的标识”,而是“同一对象的两个实例的标识,基于唯一且不变的(”immutable") 其属性的组合'。

因此,我不需要通过 map 中的内存地址来搜索车辆,而是需要具有我要查找的 ID 的车辆。

想象一个包含车主数据的数据库,在应用程序启动时加载到字典中。现在,如果用户在申请表中输入 VIN,应用程序如何在字典中找到车辆?如果代码使用 VehicleFactory.CreateVehicleFromDatabase(Edit1.Text); 创建一个新实例并在字典中搜索此对象,则 Equals 的默认实现将不会在映射中找到任何条目,因为它看起来为内存地址。为了找到车辆,Equals 需要比较 VIN。

所以我必须创建一个自定义 IEqualityComparer。实现 Equals 很简单。但是 GetHashCode 呢?对于字符串属性,我不能简单地使用字符串的地址(请参阅 Are Delphi strings immutable? 中的 Berry Kelly:“如果从两个单独的代码部分创建相同的字符串,它们将不会共享相同的后备存储”),因此字符串属性的 GetHashCode 函数需要自定义实现。

我还发现我找到了问题How do I hash a string with Delphi? - 有一个包含 HashValue('Hello World')

的示例

最佳答案

您似乎被误导,认为 Delphi 字符串没有默认的哈希代码实现。

事实并非如此。当您创建 TDictionary以字符串值作为键,根据字符串的内容计算哈希值。如果Value是一个字符串变量,那么代码如下所示:

BobJenkinsHash(Value[1], Length(Value) * SizeOf(Value[1]), 0);

我认为这回答了您有关字符串哈希的问题。

<小时/>

对其他答案的评论以及我已删除的评论是关于您正在考虑的设计问题的有趣讨论。我仍然对您的信念表示怀疑,即正确的解决方案是允许 TVehicle 实例和 VIN 之间存在多对一关系。

您已确认您不得拥有多个具有相同 VIN 但数据不同的 TVehicle 实例。在我看来,实现这一目标的最佳方法是确保 TVehicle 实例和 VIN 之间存在一对一的关系。

这种一对一的关系很容易实现。您需要将 TVehicle 实例的实例化为工厂类的私有(private)函数。该工厂类包含一个包含现有车辆实例的字典, TDictionary<string,TVehicle> 。如果您需要获得车辆,请向工厂索要。它返回位于其字典中的现有字典,或者合成一个新字典。

毫无疑问,还有许多其他方法可以实现此效果,但我强烈建议您考虑一种方法,使每个 VIN 仅产生一个车辆实例。

关于delphi - TDictionary<TVehicle, TPerson> 的 Equals 和 GetHashCode,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5315523/

相关文章:

delphi - TListView 列排序(按前两列排序)

Java thenComparing通配符签名

ios - 如何抽象网络模型获取

java - 使用 Java 8 Stream 将 Array 转换为 HashMap

delphi - 为什么这个 LEA 指令不能编译?

macos - 在MacOS上打开INI文件时出现Unicode映射错误

c# - 为什么 IsGenericParameter 对于泛型参数为假 T

java - 对集合中的现有对象或传入对象调用 equals() 方法

java - 如何为我的 Android 应用程序实现以下结构?

delphi - 升级 Indy 库以使用最新的 OpenSSL 库