在C#中迭代通用List时的性能问题

时间:2012-04-18 00:35:26

标签: c# visual-studio-2008 list generics

假设我们有这些业务对象具有一些共同的属性:

public class A
{
    // Properties in common
    public int Common { get; set; }
    public string aValue { get; set; }
    // Some other goes here.
}

public class B
{
    // Properties in common
    public int Common { get; set; }
    public string bValue { get; set; }

    // Some other goes here.
}

在我们的业务逻辑中,我们有两个像这样的列表:

List<A> aList = new List<A>();
List<B> bList = new List<B>();

(假设我们这些列表中至少填充了100个实例) 好吧,让我们从我们的问题开始,我们需要迭代aList,以便在bList中设置每个实例的一个属性,当然这个属性与共同的属性匹配,如下所示:

foreach (A a in aList)
{
    B b = bList.Find(x => x.Common == a.Common);
    if (b != null)
        b.bValue = a.aValue;
}

有没有人知道改善此操作的更好方法,因为它导致我们的应用程序需要花费太多时间才能完成?

感谢,

4 个答案:

答案 0 :(得分:4)

由于列表中的Find是线性的,因此效果不佳。生成的算法为O(n^2)

您应该使用公共属性上的Dictionary制作bList,然后按键查找,而不是使用Find进行搜索;字典查找是O(1)分摊的,因此它会使您的算法在列表长度上呈线性。

var dict = bList.ToDictionary(b => b.Common);
foreach (A a in aList) {
    B b;
    if (dict.TryGetValue(a.Common, out b) {
        b.bValue = a.aValue;
    }
}

答案 1 :(得分:2)

为了有效地查找值,给定某个键,您不会使用列表,而是使用字典。要查找列表中的特定项,需要O(N),在字典中需要O(1)。

Dictionary<int, B> bDict = new Dictionary<int, B>();
foreach (B b in bList) bDict.Add(b.Common, b);

foreach (A a in aList) {
  if (bDict.ContainsKey(a.Common)) 
    bDict[a.Common].bValue = a.aValue;
}

答案 2 :(得分:1)

将bList复制到以Common作为键的字典类型容器中,并在循环中使用它而不是bList本身。

答案 3 :(得分:1)

我相信如果您在linq中进行连接,它将在两个列表上为您执行散列连接,这将节省您手动创建字典,如其他答案中所建议的那样。我没有在这台机器上安装工作室来鞭打你的样品,稍后会尝试更新。

如果项目数量非常小,Linq甚至可能足够聪明,不会启动哈希联接。

编辑: 给这样的东西一个旋转:

var joined = from a in aList
                    join b in bList on a.Common equals b.Common
                    select new {
                            A = a,
                            B = b
                    };

            foreach (var item in joined)
            {
                    item.B.bValue = item.A.aValue;
            }