Hash 关于可变对象的散列码

Hash 关于可变对象的散列码,hash,hashtable,hashcode,Hash,Hashtable,Hashcode,我知道,我知道,有很多关于散列码的问题,但我想就计算可变对象的散列码的两种解决方案发表意见 从这个假设()开始: 通常,对于可变引用类型,只有在以下情况下才应重写GetHashCode: 您可以从不可变的字段计算哈希代码;或 当可变对象包含在依赖其哈希代码的集合中时,可以确保该对象的哈希代码不会更改 否则,您可能会认为可变对象在哈希表中丢失了 当我需要将可变对象存储到哈希表中时,哪一个是最好的选择 解决方案1 忽略这个问题。使用其中一种可用算法(此处为C#中的地理坐标示例)计算是否: 你的意

我知道,我知道,有很多关于散列码的问题,但我想就计算可变对象的散列码的两种解决方案发表意见

从这个假设()开始:

通常,对于可变引用类型,只有在以下情况下才应重写GetHashCode:

  • 您可以从不可变的字段计算哈希代码;或
  • 当可变对象包含在依赖其哈希代码的集合中时,可以确保该对象的哈希代码不会更改
否则,您可能会认为可变对象在哈希表中丢失了

当我需要将可变对象存储到哈希表中时,哪一个是最好的选择

解决方案1

忽略这个问题。使用其中一种可用算法(此处为C#中的地理坐标示例)计算是否:

你的意见是什么?

这很简单:

  • 解决方案2:如果对象o1和o2具有不同的字段值,则它们具有不同的哈希代码。如果随后更改这些对象的字段,使它们彼此相等,则它们仍然不会具有相同的哈希代码。它打破了限制:
    o1==o2意味着散列(o1)==hash(o2)
    。不可行的解决办法

  • 解决方案3:与2相同的问题

  • 解决方案1:正确的哈希函数,但每次都需要重新计算哈希代码

因此,解决方案1就是这样。如果需要对其进行优化(请记住,过早优化是万恶之源),可以缓存哈希代码,并在每次属性写入后更新:

private Int32 UpdateHashCode() {
        Int32 n1 = 99999997;
        Int32 hash_lat = this.Latitude.GetHashCode() % n1;
        Int32 hash_lng = this.Longitude.GetHashCode();
        cached_hashcode = (((hash_lat << 5) + hash_lat) ^ hash_lng);
}
private Int32 cached_hashcode = null;
public override Int32 GetHashCode() {
    if (cached_hashcode == null) {
        UpdateHashCode();
    }
    return cached_hashcode.Value;
}
private string latitude;
public string Latitude {
    set {
        latitude = value;
        UpdateHashCode();
    }
}
private string longitude;
public string Longitude {
    set {
        longitude = value;
        UpdateHashCode();
    }
}
private Int32 UpdateHashCode(){
Int32 n1=99999997;
Int32 hash_lat=this.Latitude.GetHashCode()%n1;
Int32 hash_lng=this.Longitude.GetHashCode();

cached_hashcode=((hash_lat我不知道判断解决方案的所有相关标准——但第三个标准给我的印象是最干净的,即使它有一点开销。对我来说,这听起来像是一个XY问题。你所有的解决方案都有问题。对于解决方案1,这是显而易见的(你自己编写的)。对于解决方案2和3,两个具有相同数据的对象可能会产生不同的哈希代码,这取决于哈希代码是在什么时候首先计算的。因此:您需要更好地描述您真正的问题是什么。@ThomasMueller您是对的。不管怎样,您从哪里得到的信息表明,两个具有相同数据和不同哈希代码的对象是一个问题?Is是哈希代码计算的一个要求,或者是什么?@ThomasMueller我没有具体的问题。这是我每次创建类时遇到的一个一般性问题,我知道我将在哈希集和/或可排序列表中使用这些类。在这种情况下……我建议不要将可变对象用作映射的键。所有解决方案都会阻止在中找到您的对象哈希表,除非您为解决方案传递与key.Tnx完全相同的对象,但如何解决“当对象包含在依赖其哈希代码的集合中时,可变对象的哈希代码不得更改”这一事实?
private Int32? _final_hashcode = null;
public override Int32 GetHashCode() {
    // hash code must not change when lat and lng does change
    if (_final_hashcode == null) {
        Int32 n1 = 99999997;
        Int32 hash_lat = this.Latitude.GetHashCode() % n1;
        Int32 hash_lng = this.Longitude.GetHashCode();
        _final_hashcode = (((hash_lat << 5) + hash_lat) ^ hash_lng);
    }
    return _final_hashcode.Value;
}
public class GeoPosition {

    private const Guid _guidForHash = Guid.NewGuid(); // init during contruction

    public override Int32 GetHashCode() {
        return _guidForHash.GetHashCode();
    }

    // mutable properties here and other stuff
    // ...
}
private Int32 UpdateHashCode() {
        Int32 n1 = 99999997;
        Int32 hash_lat = this.Latitude.GetHashCode() % n1;
        Int32 hash_lng = this.Longitude.GetHashCode();
        cached_hashcode = (((hash_lat << 5) + hash_lat) ^ hash_lng);
}
private Int32 cached_hashcode = null;
public override Int32 GetHashCode() {
    if (cached_hashcode == null) {
        UpdateHashCode();
    }
    return cached_hashcode.Value;
}
private string latitude;
public string Latitude {
    set {
        latitude = value;
        UpdateHashCode();
    }
}
private string longitude;
public string Longitude {
    set {
        longitude = value;
        UpdateHashCode();
    }
}