zoukankan      html  css  js  c++  java
  • 项目经验总结(三)哪种方式查询泛型集合性能上最佳

        这篇文章我来分析下对于泛型集合,采取不同的查询方式在性能上会有什么样的影响?

        这里有一个城市简单信息的实体类:
        

    代码
    class CityInfo
        {
            
    public int CityID
            {
                
    get;
                
    set;
            }
            
    public string CityName
            {
                
    get;
                
    set;
            }
            
    public string CityNameEn
            {
                
    get;
                
    set;
            }
            
    public string CityAddress 
            { 
                
    get
                
    set;
            }
        }

         我们构造一个特别大的城市泛型类:
         

    代码
                int i = 100000;
                Random m 
    = new Random();
                List
    <CityInfo> list = new List<CityInfo>();
                
    for (int j = 0; j < i; j++)
                {
                    CityInfo info 
    = new CityInfo();
                    info.CityID 
    = j;
                    info.CityAddress 
    = "aaaaaa" + j.ToString();
                    info.CityName 
    = "城市中文名称" + j.ToString();
                    info.CityNameEn 
    = "城市英文名称" + j.ToString();
                    list.Add(info);
                }

         根据城市ID查询某个城市的具体信息:
         方法一:foreach:
           

    代码
            static CityInfo GetCityInfoByForeach(List<CityInfo> list, int CityID)
            {
                CityInfo info 
    = new CityInfo();
                
    foreach (var item in list)
                {
                    
    if (item.CityID == CityID)
                    {
                        info 
    = item;
                        breake;
                    }
                }
                
    return info;
            }

          方法二:for循环:
          

    代码
            static CityInfo GetCityInfoByFor(List<CityInfo> list, int CityID)
            {
                CityInfo info 
    = new CityInfo();
                
    for (int i = 0; i < list.Count;i ++ )
                {
                    
    if (list[i].CityID == CityID)
                    {
                        info 
    = list [i];
                        breake;

                     }
                }
                
    return info;
            }

         方法三:Linq查询:
         

    代码
            static CityInfo GetCityInfoByLinq(List<CityInfo> list,int CityID)
            {
                CityInfo info 
    = new CityInfo();
                info 
    = list.Where(p => p.CityID == CityID).FirstOrDefault();
                
    return info;
            }

          然后随机产生一个城市ID,分别针对上面三种方式调用500次,这里何用老赵的CodeTimer来显示信息,执行结果如下:

         

    代码
           CodeTimer.Time("GetCityInfoByForeach"500, () => GetCityInfoByForeach(list, m.Next(i - 1)));
           CodeTimer.Time(
    "GetCityInfoByFor"500, () => GetCityInfoByFor(list, m.Next(i - 1)));
           CodeTimer.Time(
    "GetCityInfoByLinq"500, () => GetCityInfoByLinq(list, m.Next(i - 1)));

         

      

           性能从高到低表现为:for,foreach,linq,仔细查看三种方法生成IL代码,有一定的区别:
           1:foreach方法在查询数据时,依赖了Enumerator ,它的特点是不能像对于数组一样使用索引,而只能将当前项指针移动到集合的第一个或下一个元素,这是它性能不是最优的主要问题所在。在这种方式中还有一个重要点就是在查询每个元素时都会有try finally块,这也是需要消耗部分性能的。
          

    代码
      .try
      {
        IL_000d:  br.s       IL_0022
        IL_000f:  ldloca.s   CS$
    5$0000
        IL_0011:  call       instance 
    !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<class ConsoleApplication1.CityInfo>::get_Current()
        IL_0016:  stloc.
    1
        IL_0017:  ldloc.
    1
        IL_0018:  callvirt   instance int32 ConsoleApplication1.CityInfo::get_CityID()
        IL_001d:  ldarg.
    1
        IL_001e:  bne.un.s   IL_0022
        IL_0020:  ldloc.
    1
        IL_0021:  stloc.
    0
        IL_0022:  ldloca.s   CS$
    5$0000
        IL_0024:  call       instance 
    bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<class ConsoleApplication1.CityInfo>::MoveNext()
        IL_0029:  brtrue.s   IL_000f
        IL_002b:  leave.s    IL_003b
      }  
    // end .try
      finally
      {
        IL_002d:  ldloca.s   CS$
    5$0000
        IL_002f:  constrained. valuetype [mscorlib]System.Collections.Generic.List`
    1/Enumerator<class ConsoleApplication1.CityInfo>
        IL_0035:  callvirt   instance 
    void [mscorlib]System.IDisposable::Dispose()
        IL_003a:  endfinally
      }  
    // end handler

          2:for方法在查询数据时,System.Collections.Generic.List`1<class ConsoleApplication1.CityInfo>::get_Item(int32),比起foreach少了try的处理,最重要的是能够使用索引访问元素。

          3:linq方式性能最差。

          非常感谢各位朋友的指点,特别是代码中忘记加break,现在是修改代码后的测试结果:结果和上面一样。

         

     

          本篇文章的测试代码

      

          总结:泛型集合如果数据量大,最好采用for循环查询,数据量少的话,用linq方式最佳,代码优雅且简洁。

          题外话:其实针对这种泛型集合查询,如果想优化性能,最好不要存储成泛型集合,采用Dictionary或者是hashtable效果更佳。

  • 相关阅读:
    PHP 使用 GET 传递数组变量
    Java实现 蓝桥杯 算法训练 数据交换
    Java实现 蓝桥杯 算法训练 数据交换
    Java实现 蓝桥杯 算法训练 数据交换
    Java实现 蓝桥杯 算法训练 景点游览
    Java实现 蓝桥杯 算法训练 景点游览
    Java实现 蓝桥杯 算法训练 景点游览
    Java实现 蓝桥杯 算法训练 二进制数数
    Java实现 蓝桥杯 算法训练 二进制数数
    Java实现 蓝桥杯 算法训练 二进制数数
  • 原文地址:https://www.cnblogs.com/ASPNET2008/p/1868633.html
Copyright © 2011-2022 走看看