我可以在没有 Equals 的情况下使用 GetHashCode 吗?
Can I use GetHashCode without Equals?
可能是我没看懂。不,我绝对不明白什么。有一个带有两个 int 类型属性的自定义 class。覆盖 GetHashCode 方法,我想使用这两个属性作为获取哈希码的基础。但是,由于GetHashCode方法的return类型是int,而我的class中的两个属性都是int。结果发现我的属性的各种值的组合会比int类型容纳的多。结果,无论如何,我都会有碰撞。正确的?
此外,我想说的是,我尝试了几种标记为可接受答案的算法,这些算法来自其他主题,其中包括 Jon Skeet 等权威人士提供的选项,但仍然存在冲突。
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);
}
}
我怀疑您正试图将 GetHashCode
用于不适合的用途。
查看 this SO answer 了解更多上下文。
我不完全确定我理解 if (d.TryGetValue(hash, out var saved))
背后的意图 - 我假设您想检查是否已将此特定行保存到 CSV 中。如果确实如此,您可能会发现维护 HashSet 更容易,因为它基本上屏蔽了您的 int
密钥,同时允许您检查唯一性:
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);
}
可能是我没看懂。不,我绝对不明白什么。有一个带有两个 int 类型属性的自定义 class。覆盖 GetHashCode 方法,我想使用这两个属性作为获取哈希码的基础。但是,由于GetHashCode方法的return类型是int,而我的class中的两个属性都是int。结果发现我的属性的各种值的组合会比int类型容纳的多。结果,无论如何,我都会有碰撞。正确的? 此外,我想说的是,我尝试了几种标记为可接受答案的算法,这些算法来自其他主题,其中包括 Jon Skeet 等权威人士提供的选项,但仍然存在冲突。
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);
}
}
我怀疑您正试图将 GetHashCode
用于不适合的用途。
查看 this SO answer 了解更多上下文。
我不完全确定我理解 if (d.TryGetValue(hash, out var saved))
背后的意图 - 我假设您想检查是否已将此特定行保存到 CSV 中。如果确实如此,您可能会发现维护 HashSet 更容易,因为它基本上屏蔽了您的 int
密钥,同时允许您检查唯一性:
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);
}