如何通过密钥哈希码访问字典?

时间:2016-11-17 13:31:25

标签: c# dictionary

我有这样的字典:

 Dictionary<MyCompositeKey, int>

显然MyCompositeKey是我设计的一个实现IEqualityComparer的类,因此具有GetHashCode方法。

据我所知,词典使用键的哈希值来访问该值,所以这就是我的问题:

虽然我可以通过dict.TryGetValue(new MyCompositeKey(params))轻松访问该值,但我希望在每次访问时摆脱new开销。

出于这个原因,我想知道是否有办法直接从密钥的哈希值(我可以用非常低的开销计算)来访问该值。

2 个答案:

答案 0 :(得分:2)

没有办法做到这一点。

请注意,可能会发生哈希冲突,因此Dictionary<,>中可能存在与给定哈希匹配的许多键。我们需要Equals来找出哪个(如果有的话)是正确的。

你谈论new开销。你确定它对你来说很重要吗?

如果是,您可以考虑将MyCompositeKey设为不可变 struct而不是class。在某些情况下可能会更快,从而无需垃圾收集器从内存中删除所有“松散”密钥。

如果MyCompositeKeystruct,则表达式new MyCompositeKey(params)仅将所有params加载到调用堆栈(或CPU寄存器或任何运行时数字最佳) )。

添加:如果您选择struct,请考虑实施IEquatable<>。它看起来像这样:

struct MyCompositeKey : IEquatable<MyCompositeKey>
{
  // readonly fields/properties

  public override bool Equals(object obj)
  {
    if (obj is MyCompositeKey)
      return Equals((MyCompositeKey)obj); // unbox and go to below overload

    return false;
  }

  public bool Equals(MyCompositeKey other) // implements interface, can avoid boxing
  {
    // equality logic here
  }

  public override int GetHashCode()
  {
    // hash logic here
  }
}

答案 1 :(得分:1)

你做不到。

Dictionary<TKey, TValue>使用您无法从课外访问的内部存储桶集合 - 它是private

正如您在source code中看到的,访问方法首先确定存储桶(根据哈希码),然后按索引访问项目:

public bool TryGetValue(TKey key, out TValue value) 
{
    int i = FindEntry(key);
    if (i >= 0) 
    {
        value = entries[i].value;
        return true;
    }

    value = default(TValue);
    return false;
}

private int FindEntry(TKey key) 
{
    if (buckets != null) 
    {
        int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
        for (int i = buckets[hashCode % buckets.Length]; i >= 0; i = entries[i].next) 
        {
            if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) 
                return i;
        }
    }

    return -1;
}