zoukankan      html  css  js  c++  java
  • C# ContainsKey与TryGetValue方法探究

    最近在进行在做一个链路选择的需求,涉及到字典存储。发现C#的Dictionary提供了ContainsKey和TryGetValue两个方法,都可以来判断字典中是否存在对应的Key值。那么这两个方法有什么区别呢?我们在编写代码的过程中如何选取呢?

    我先创建了一个Dictionary<string, int>的字典,然后从0递增到一千万分别给这个字典添加了数据。

    static Dictionary<string, int> dic = new Dictionary<string, int>();
    const int TOTALNUM = 10000000;
    
    for (int i = 0; i < TOTALNUM; i++)
    {
        dic.Add(i.ToString(), i);
    }
    

    我们借助StopWatch,对ContainsKey和TryGetValue分别进行一千万次的查找,比较两者所花费的时间。

    Stopwatch stopwatch1 = new Stopwatch(); // TryGetValue
    Stopwatch stopwatch2 = new Stopwatch(); // COntainsKey
    

    测试环境:

    • IDE工具:VS2019
    • CPU:i7-8700
    1. 当取出的Value在执行过程中有被使用时:

      stopwatch1.Start();
      long a = 0;
      for (int i = 0; i < TOTALNUM; i++)
      {
          string str = i.ToString();
          if (dic.TryGetValue(str, out var value))
          {
              // Value被使用
              a = a + value;
          }
      }
      stopwatch1.Stop();
      
      stopwatch2.Start();
      long b = 0;
      for (int i = 0; i < TOTALNUM; i++)
      {
          string str = i.ToString();
          if (dic.ContainsKey(str))
          {
              // Value被使用
              b = b + dic[str];
          }
      }
      stopwatch2.Stop();
      

      ContainsKey所花费的时间较多

    2. 当没有对字典所对应Key的Value进行操作时:

      ...
          if (dic.TryGetValue(str, out var value))
          {
              a = a + 1;
          }
      ...
      
      ...
          if (dic.ContainsKey(str))
          {
              b = b + 1;
          }
      ...
      

      TryGetValue花费的时间更多

    3. 查看源码:

      public bool TryGetValue(TKey key, out TValue value)
      {
          int index = this.FindEntry(key);
          if (index >= 0)
          {
              value = this.entries[index].value;
              return true;
          }
          value = default(TValue);
          return false;
      }
      
      public bool ContainsKey(TKey key)
      {
          return (this.FindEntry(key) >= 0);
      }
      
      
      public TValue this[TKey key] 
      {
      	get 
          {
          	int i = FindEntry(key);
              if (i >= 0) return entries[i].value;
              ThrowHelper.ThrowKeyNotFoundException();
              return default(TValue);
          }
          set 
          {
          	Insert(key, value, false);
          }
      }
      

      查看源码我们发现TryGetValue是在ContainsKey的基础上直接从存储中取出Value。有一个很关键的函数FindEntry我们在三个函数都有看到,说明我们如果在使用完ContainsKey在用Dic[Key]去取值的时候,会多一次开销。

    总结

    • 在数据量不大的情况下,两者并没有太大的差别。在数据量大的情况下,如果对Value并没有操作推荐用ContainsKey,反之则使用TryGetValue。当Key的命中率远低于50%,且操作Value时,也可以考虑使用ContainsKey。

  • 相关阅读:
    PAT Basic 1077 互评成绩计算 (20 分)
    PAT Basic 1055 集体照 (25 分)
    PAT Basic 1059 C语言竞赛 (20 分)
    PAT Basic 1072 开学寄语 (20 分)
    PAT Basic 1049 数列的片段和 (20 分)
    蓝桥杯BASIC-13 数列排序
    蓝桥杯入门——3.序列求和
    蓝桥杯入门——2.圆的面积
    蓝桥杯入门——1.Fibonacci数列
    树的总结(遍历,BST,AVL原型,堆,练习题)
  • 原文地址:https://www.cnblogs.com/fzuljz/p/14495697.html
Copyright © 2011-2022 走看看