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。

  • 相关阅读:
    列表 ,表格与媒体元素基础
    HTML5基础知识
    解析
    字符串
    类和对象
    [leetcode]605. Can Place Flowers能放花吗
    [leetcode]432. All O`one Data Structure全O(1)数据结构
    [leetcode]68. Text Justification文字对齐
    [leetcode]149. Max Points on a Line多点共线
    [leetcode]272. Closest Binary Search Tree Value II二叉搜索树中最近的值II
  • 原文地址:https://www.cnblogs.com/fzuljz/p/14495697.html
Copyright © 2011-2022 走看看