2

我有一个对象,我想用它来查找其他对象。我将使用Dictionary<TKey, TValue>().

关键对象有两个唯一标识它的字符串,比如KeyObj.Str1KeyObj.Str2

你建议我用什么作为字典的键?

1:字符串的连接。

Dictionary<String, TValue>();
Key = KeyObj.Str1:KeyObj.Str2; ("somestring:anotherstring")

2:每个对象用一个唯一的整数来标识吗?

Dictionary<int, TValue>();
KeyObj.ID = _nextID++;
Key = KeyObj.ID;

3:对对象的引用。

Dictionary<KeyObj, TValue>();
Key = KeyObj;

选项 3 将是最简单的,但似乎基于参考值索引字典效率低下。

如果 key 对象包含一个唯一的字符串,那么明显的选择是使用它,但是只有两个唯一的字符串组合起来会变得更加困难。

4

9 回答 9

2

串联的字符串应该效果最好。

如果您知道它们的组合是唯一的,那么这就是您应该选择的——记住哈希码通常是唯一的,但并非总是如此。

于 2009-03-20T16:02:45.263 回答
2

如果您可以适当地覆盖 GetHashCode() 和 Equals() ,则可以使用选项 3,例如:

    public override int GetHashCode()
    {
        return str1.GetHashCode() ^ str2.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        if (!obj is KeyObj)
        {
            return false;
        }

        KeyObj key = (KeyObj)obj;
        return this.str1.Equals(key.str1) && this.str2.Equals(key.str2);
    }
于 2009-03-20T16:11:36.490 回答
1

连接它们可能是最好的主意。您可以在执行连接的对象中公开一个属性,KeyObj这样您就不必在每次访问字典值时都执行它。

编辑:

我显然误读了这个问题。我认为您真正想要做的是 1 和 3 的混合,您可以覆盖Equals()GetHashCode()使用string唯一标识对象的 s(只要确保它们是不可变的!)

public override Equals(object obj) 
{
   if (obj == null || !(obj is KeyObj))
      return false;
   KeyObj other = (KeyObj)obj;
   if (this.Key1 == other.Key1 && this.Key2 == other.Key2)
     return true;
   return false;
}

public override GetHashCode()
{
    return (this.Key1 + this.Key2).GetHashCode();
}

然后你可以使用你建议的第三个选项:

Dictionary<KeyObj, ValueObj>...
于 2009-03-20T16:01:55.437 回答
1

使用 KeyObj.GetHashCode() 怎么样?

于 2009-03-20T16:02:07.810 回答
1

它们中的任何一个都是有效的,但我假设您希望能够根据两个字符串之一快速找到这些对象,因此使用 int 作为键意味着您仍然必须扫描值以找到你想要的对象。

字符串都是唯一的,还是仅在组合时才唯一?如果它们都是独一无二的,并且您愿意交换一些空间,您可以这样做:

dict.Add(KeyObj.Str1, KeyObj);
dict.Add(KeyObj.Str2, KeyObj);

并且有两个对字典中对象的引用,使用每个唯一的字符串作为键。或者,如果它们只是唯一的字符串,您总是可以将它们组合在一起,并且它将在内部使用哈希码来查找它们。

于 2009-03-20T16:02:28.120 回答
0

您不需要使用新类作为字典键。改用新的结构,因为它会更轻量级......并且显然它由这两个字符串值组成。

于 2009-03-20T15:58:54.383 回答
0

如果性能是主要考虑因素,您可以考虑使用两个字符串的哈希值。但是,您的“值”字段必须同时包含键和值。

我有另一个 SO question 的参考,我只需要找到它。

通过哈希码在数据库中搜索大字符串是否更快?

但是这个问题更面向数据库。并且性能被考虑了数千次迭代。

于 2009-03-20T16:00:09.623 回答
0

请记住,字典是一个美化的哈希表,因此键(不是双关语)是使用一个键,该键将导致与另一个键的冲突极少(如果有的话)。我倾向于#3,但这是假设 KeyObj 类型具有良好的哈希值生成器。

于 2009-03-20T16:03:04.983 回答
0

字符串作为键是最好的,请参阅我的测试代码:

var tupleKeyDict = 新字典,字符串>();

        for (int i = 0; i < 1000000; i++)
        {
            tupleKeyDict.Add(new Tuple<int, int>(i,0),i.ToString() );
        }

        System.Diagnostics.Stopwatch stopWatch = new Stopwatch();
        stopWatch.Start();
        string e1 = tupleKeyDict[new Tuple<int, int>(0, 0)];
        string e2 = tupleKeyDict[new Tuple<int, int>(500000, 0)];
        string e3 = tupleKeyDict[new Tuple<int, int>(999999, 0)];
        stopWatch.Stop();
        Console.WriteLine("Tuplekey cost(tick): " + stopWatch.ElapsedTicks.ToString());
        Console.WriteLine("Tuplekey cost(ms): " + stopWatch.ElapsedMilliseconds.ToString());





        var strKeyDict = new Dictionary<string, string>();

        for (int i = 0; i < 1000000; i++)
        {
            strKeyDict.Add(i.ToString() + ":0", i.ToString());
        }

        System.Diagnostics.Stopwatch stopWatch2 = new Stopwatch();
        stopWatch2.Start();
        string se1 = strKeyDict["0:0"];
        string se2 = strKeyDict["500000:0"];
        string se3 = strKeyDict["999999:0"];
        stopWatch2.Stop();
        Console.WriteLine("strkey cost(tick): " + stopWatch2.ElapsedTicks.ToString());
        Console.WriteLine("strkey cost(ms): " + stopWatch2.ElapsedMilliseconds.ToString());




        var intKeyDict = new Dictionary<int, string>();

        for (int i = 0; i < 1000000; i++)
        {
            intKeyDict.Add(i, i.ToString());
        }

        System.Diagnostics.Stopwatch stopWatch3 = new Stopwatch();
        stopWatch3.Start();
        string ie1 = intKeyDict[0];
        string ie2 = intKeyDict[500000];
        string ie3 = intKeyDict[999999];
        stopWatch3.Stop();
        Console.WriteLine("intkey cost(tick): " + stopWatch3.ElapsedTicks.ToString());
        Console.WriteLine("intkey cost(ms): " + stopWatch3.ElapsedMilliseconds.ToString());

输出: Tuplekey cost(tick): 104 Tuplekey cost(ms): 0 strkey cost(tick): 12 strkey cost(ms): 0 intkey cost(tick): 66 intkey cost(ms): 0

于 2014-01-09T02:27:47.870 回答