开发者

Inserting twice the same key in a HashTable, how is that possible?

开发者 https://www.devze.com 2023-01-25 07:09 出处:网络
I am trying to understand how works the key sorting / insertion check in a hashtable. I\'ve understood that when I\'m adding an object to a hashtable, it checks at runtime that there isn\'t the same k

I am trying to understand how works the key sorting / insertion check in a hashtable. I've understood that when I'm adding an object to a hashtable, it checks at runtime that there isn't the same key already entered in there.

In my test, I've 2 hashtables which keys are filled in with: 1- Integers 2- An object which I've overriden the GetHashCode method to return always 1.

My issue here: while the first test is breaking when adding the same int key, the second test isn't! How come? The hashcodes that should be checked at the insertion are all returning 1.

Thank you in advance!


My code:

class Collections
{
    public Collections()
    {
        // Testing a hashtable with integer keys
        Dictionary<int, string> d1 = new Dictionary<int, string>();
        d1.Add(1, "one");
        d1.Add(2, "two");
        d1.Add(3, "three");
        // d1.Add(3, "three"); // Cannot add the same key, i.e. same hashcode
        foreach (int key in d1.Keys)
            Console.WriteLine(key);

        // Testing a hashtable with objects returning only 1 as hashcode for its keys
        Dictionary<Hashkey, string> d2 = new Dictionary<Hashkey, string>();
        d2.Add(new Hashkey(1), "one");
        d2.Add(new Hashkey(2), "two");
        d2.Add(new Hashkey(3), "three");
        d2.Add(new Hashkey(3), "three");
        for (int i = 0; i < d2.Count; i++)
            Console.WriteLine(d2.Keys.ElementAt(i).ToString());

    }


}

/// <summary>
/// Creating a class that is serving as a key of a hasf table, overring the GetHashcode() of System.Object
/// </summary>
class Hashkey
{
    public int Key { get; set; }

    public Hashkey(int key)
    {
        this.Key = key;
    }

    // Overriding the Hashcode to return always 1
    public override int GetHashCode()
    {
        return 1;
        // return base.GetHashCode();
    }

    // No override
    public override bool Equals(object obj)
    {
        return base.Equals(obj);
    }

    // returning the name of the object
    public override string ToString()
    {
        return this.Key.ToString()开发者_运维知识库;
    }        
}

}


Dictionary will check for the hash code and object equality. The hash is just used to come up with a "first approximation" to find possibly equal keys very efficiently.

Your override of Equals just delegates to the base implementation, which uses reference equality. That means any two distinct instances of HashKey are unequal, even if they have the same value for the Key property.

What are you actually trying to achieve? Or are you just trying to understand how GetHashCode and Equals relate to each other?


The hash code is merely an heuristic to choose the right bucket to store the item in. Just because 2 items share the same hashcode doesn't mean that they are equal. In the case of collision (as will be occurring with your 1 hashcode), we revert to simple search within the bucket to find members that are equal to the searched key. As your equality test is checking if the references are the same, no 2 items will ever be equal.


The Equals compares the reference of the HashKey.

Because that are different instances, they are not equal.

Your Equals should look like this:

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(this, obj))
            return true;

        var other = obj as Hashkey;

        return
            other != null &&
            Key.Equals(other.Key);
    }
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号