代码之家  ›  专栏  ›  技术社区  ›  SuperJMN

为什么具有相同元素的哈希集在调用getHashCode()时返回不同的值?

  •  2
  • SuperJMN  · 技术社区  · 6 年前

    为什么? HashSet<T>.GetHashCode() 返回具有相同元素的不同哈希代码?

    例如:

    [Fact]
    public void EqualSetsHaveSameHashCodes()
    {
        var set1 = new HashSet<int>(new [] { 1, 2, 3 } );
        var set2 = new HashSet<int>(new [] { 1, 2, 3 } );
    
        Assert.Equal(set1.GetHashCode(), set2.GetHashCode());
    }
    

    此测试失败。为什么?

    我怎样才能得到我需要的结果? “相等集提供相同的哈希代码”

    3 回复  |  直到 6 年前
        1
  •  2
  •   InBetween    6 年前

    HashSet<T> 默认情况下没有值相等语义。它具有引用相等语义,因此即使包含元素相同,两个不同的哈希集也不会相等或具有相同的哈希代码。

    你需要用一个特殊的目的 IEqualityComparer<HashSet<int>> 为了得到你想要的行为。您可以自己滚动或使用框架为您提供的默认值:

    var hashSetOfIntComparer = HashSet<int>.CreateSetComparer();
    
    //will evaluate to true
    var haveSameHash = hashSetOfIntComparer.GetHashCode(set1) ==
                       hashSetOfIntComparer.GetHashCode(set2);
    

    因此,长话短说:

    我怎样才能得到我需要的结果? “相等集提供相同的哈希代码”

    如果计划使用的默认实现 HashSet<T>.GetHashCode() . 您要么使用特殊用途比较器,要么扩展 哈希集<t> 超驰 Equals GetHashCode 以满足您的需求。

        2
  •  1
  •   Adam G    6 年前

    默认情况下(除非另有明确说明),只有引用同一对象时,才认为引用类型是相等的。作为开发人员,您可以重写equals()和gethashcode()方法,以便您认为相等的对象对equals返回true,对gethashcode返回相同的int。

    根据您使用的测试框架,将有collectionassert.areequivalent()或需要比较器的override to assert.equal。

        3
  •  -1
  •   Nathan Werry    6 年前

    您可以实现一个自定义散列集,该散列集重写gethashcode函数,该函数从以下所有内容生成一个新的散列代码:

    public class HashSetWithGetHashCode<T> : HashSet<T>
    {
        public override int GetHashCode()
        {
            unchecked // Overflow is fine, just wrap
            {
                int hash = 17;
                foreach (var item in this)
                    hash = hash * 23 + item.GetHashCode();
                return hash;
            }
        }
    }