简体   繁体   中英

Can I use GetHashCode without Equals?

Maybe I don't understand something. No, I definitely don't understand something. There is a custom class with two int type properties. Overriding the GetHashCode method, I want to use both of these properties as the basis for obtaining the hash code. But, since the return type of the GetHashCode method is int, and the two properties in my class have int. It turns out that there will be more combinations of various values ​​of my properties than the int type can accommodate. As a result, in any case, I will have collisions. Right? In addition, I want to say that I tried several algorithms marked as acceptable answers, from other topics in which, among others, authoritative people such as Jon Skeet offered their options, but still got collisions.

    public class Equivalent
    {
        public Equivalent(int a, int b)
        {
            A = a;
            B = b;
        }

        public int A { get; }
        public int B { get; }

        public override int GetHashCode()
        {
            var vals = new[]
            {
                A.GetHashCode(),
                B.GetHashCode()
            };

            var hash1 = (5381 << 16) + 5381;
            var hash2 = hash1;

            var i = 0;
            foreach (var hashCode in vals)
            {
                if (i % 2 == 0)
                    hash1 = ((hash1 << 5) + hash1 + (hash1 >> 27)) ^ hashCode;
                else
                    hash2 = ((hash2 << 5) + hash2 + (hash2 >> 27)) ^ hashCode;

                ++i;
            }

            return hash1 + (hash2 * 1566083941);
        }

        public override string ToString()
        {
            return $"{A};{B}";
        }
    }

    public void GetHash()
    {
        var len = 1000000;
        var d = new Dictionary<int, Equivalent>();
        for (var i = 0; i < len; i++)
        {
            var eq = new Equivalent(
                _r.Next(int.MinValue, int.MaxValue),
                _r.Next(int.MinValue, int.MaxValue));

            var hash = eq.GetHashCode();
            if (d.TryGetValue(hash, out var saved))
            {
                File.AppendAllText("result2.csv", $"{hash};{saved}\n");
                File.AppendAllText("result2.csv", $"{hash};{eq}\n");
                continue;
            }

            d.Add(hash, eq);
            Thread.Sleep(1);
        }
    }

I suspect you are trying to use GetHashCode for something it's not meant for. Check out this SO answer for a bit more context.

I am not entirely sure I understand the intent behind the if (d.TryGetValue(hash, out var saved)) - I am assuming you want to check if you already saved this particular line into your CSV. If that is indeed the case you might find it easier maintain a HashSet because it basically masks away your int key while allowing you to check for uniqueness:

    for (var i = 0; i < len; i++)
    {
        var eq = new Equivalent(
            _r.Next(int.MinValue, int.MaxValue),
            _r.Next(int.MinValue, int.MaxValue));

        if(!d.Contains(eq))
        {
            //File.AppendAllText("result2.csv", $"{hash};{saved}\n"); // do you need this line?
            File.AppendAllText("result2.csv", $"{eq.GetProperSha1Hash()};{eq}\n");//you will need to implement the method, but there's plenty examples
            d.Add(eq);
            continue;
        }
        Thread.Sleep(1);
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM