我有两个字符串,我想将它们用作字典键,但我懒得创建另一个对象,计算字符串的哈希码等。
所以,可以获取两个字符串的哈希码,将它们相加,然后使用结果作为字典的键吗?
这样做可能会导致冲突吗?
你有什么想法?
所以,可以获取两个字符串的哈希码,将它们相加,然后使用结果作为字典的键吗?
这样做可能会导致冲突吗?
你有什么想法?
Tuple<T1, T2>
类作为键,其中T1和T2 = string。Tuple<T1, T2>
公式大约如下(未记录或保证不会更改):((h1 << 5) + h1) ^ h2
,这对于您的目的而言应该足够好了。顺便说一句,朴素地添加不是通常结合哈希码的最佳方式。如果您正在使用.NET 4,您可以使用Tuple类:
Dictionary<Tuple<string, string>, TValue> dict = new ...
如果您没有使用.NET 4,您应该创建自己的类型来保存这个。
您可以使用KeyValuePair结构体,但它会继承相关的基本值类型方法,并且因此严重依赖于反射。这对性能有影响(请参见答案底部)。
对于KeyValuePair:
Dictionary<KeyValuePair<string, string>, TValue> dict = new ...
如果您不想自己编写,可以使用以下通用类型:
public struct SimpleTuple<TValue1, TValue2>
{
private readonly TValue1 _Value1;
private readonly TValue2 _Value2;
public SimpleTuple(TValue1 value1, TValue2 value2)
{
_Value1 = value1;
_Value2 = value2;
}
public TValue1 Value1 { get { return _Value1; } }
public TValue2 Value2 { get { return _Value2; } }
public int GetHashCode()
{
unchecked
{
int result = 37;
result *= 23;
if Value1 != null)
result += Value1.GetHashCode();
result *= 23;
if (Value2 != null)
result += Value2.GetHashCode();
return result;
}
}
public override bool Equals(object obj)
{
if (obj == null) return false;
if (obj.GetType() != typeof(SimpleTuple<TValue1, TValue2>))
return false;
var other = (SimpleTuple<TValue1, TValue2>)obj;
return Equals(other.Value1, Value1) && Equals(other.Value2, Value2);
}
}
dict.Add(key, value);
这将添加或覆盖现有内容:
dict[key] = value;
回应Ani的评论,我为LINQPad编写了以下简单的测试脚本。输出结果如下:
KeyValuePair: 975毫秒 MyKeyValuePair: 52毫秒
脚本:
void Main()
{
const int iterations = 10 * 1000 * 1000;
// JIT preheat
Test1(1);
Test2(1);
Stopwatch sw = Stopwatch.StartNew();
Test1(iterations);
sw.Stop();
Debug.WriteLine("KeyValuePair: " + sw.ElapsedMilliseconds + "ms");
sw = Stopwatch.StartNew();
Test2(iterations);
sw.Stop();
Debug.WriteLine("MyKeyValuePair: " + sw.ElapsedMilliseconds + "ms");
}
public static void Test1(int iterations)
{
for (int index = 0; index < iterations; index++)
{
var kvp = new KeyValuePair<int, int>(index, index);
kvp.GetHashCode();
}
}
public static void Test2(int iterations)
{
for (int index = 0; index < iterations; index++)
{
var kvp = new MyKeyValuePair<int, int>(index, index);
kvp.GetHashCode();
}
}
public struct MyKeyValuePair<TKey, TValue>
{
private readonly TKey _Key;
private readonly TValue _Value;
public MyKeyValuePair(TKey key, TValue value)
{
_Key = key;
_Value = value;
}
public TKey Key { get { return _Key; } }
public TValue Value { get { return _Value; } }
public int GetHashCode()
{
unchecked
{
int result = 37;
result *= 23;
if (Key != null)
result += Key.GetHashCode();
result *= 23;
if (Value != null)
result += Value.GetHashCode();
return result;
}
}
public override bool Equals(object obj)
{
if (obj == null) return false;
if (obj.GetType() != typeof(MyKeyValuePair<TKey, TValue>))
return false;
var other = (MyKeyValuePair<TKey, TValue>)obj;
return Equals(other.Key, Key) && Equals(other.Value, Value);
}
}
System.ValueType
,因为它似乎没有覆盖它们。 - Anivar dict = new Dictionary<Tuple<string,string>,SomeType>();
dict.Add(Tuple.Create("Hello","World"), new SomeType());
一个简单的解决方案,适用于所有版本的.net。只需将字符串连接起来即可。
var dictionary = new Dictionary<string, int>();
dictionary.Add("The meaning" + " of life, the universe, and everything", 42);
当然,这只适用于2个字符串(虽然您可以在许多其他类型上使用.ToString()),如果您不需要仅使用两个字符串之一查找字典,但如果您拥有两者,那么它就非常简单。