检查通用列表内容的最佳方法

时间:2008-12-15 14:01:26

标签: c# .net performance generics

我必须处理一些使用通用列表来存储自定义对象集合的代码。

然后它执行类似下面的操作来检查集合中的给定对象是否存在并执行某些操作:

List<CustomObject> customObjects;
//fill up the list
List<CustomObject> anotherListofCustomObjects;
//fill it up

//...

foreach (CustomObject myCustomObject in customObjects)
{
   if (anotherListofCustomObjects.Contains(myCustomObject))
   {
      //do stuff
   }
}

问题在于永远处理7000个这样的对象。

这不是我的代码 - 我只是试图提出改进它的选项 - 在我看来,使用字典来获取密钥而不是像上面这样循环整个集合会快得多。

建议?

8 个答案:

答案 0 :(得分:9)

除了词典之外,另一种方法是,如果你使用的是.NET 3.5,那么将Linq用于对象和相交:

foreach(CustomObject c in customObjects.Intersect(anotherListOfCustomObjects))
{
    // do stuff.
}

根据反射器,它使用基于散列的集合来执行序列的交集。

答案 1 :(得分:3)

嗯,你似乎已经自己回答了吗?如果您需要对一组数据进行快速查询,那么字典可能比平面列表更好(对于较大的数据大小,您的数据大小)。

例如,您可以将对象用作自己的密钥 -

Dictionary<CustomObject,CustomObject> ...

请注意,平等的含义取决于上下文。如果您传入的是原始参考,那么这很好 - ContainsKey可以完成这项工作。如果你有一个不同但相似的用于平等的对象,那么你需要实现自己的GetHashCode()Equals(),理想情况下IEquatable<CustomObject>。可以在CustomObject本身,也可以在自定义IEqualityComparer<CustomObject>中使用。

答案 2 :(得分:2)

实际上你的代码目前是O(n ^ 2),这将是缓慢的。你可以:

  • 使用词典或KeyedCollections,这将使其成为O(nlog n)
  • 如果您可以确保这些项目的顺序相同,则可以重写最后一个循环以仅使用一个索引,这将是O(n)

答案 3 :(得分:1)

您可能还会考虑System.Collections.ObjectModel.KeyedCollection<TKey, TItem>

为了补充这一点,我通常创建自己的IKeyable接口和KeyedCollection的特定实现,它使用IKeyable进行所需的重载。

答案 4 :(得分:1)

考试是你的朋友。集合的大小决定了您应该使用的数据结构/算法。我建议你对以下选项做一些性能基准测试:

  1. 您当前的解决方案
  2. 在排序列表中使用BinarySearch算法。
  3. 使用HashSet<CustomObject>
  4. 考虑到元素的数量,我怀疑HashSet<CustomObject>是可行的方法。

答案 5 :(得分:0)

如果必须维护两个单独的列表,则其中一个Set类型可能更快(使用Join操作)。一些可用的库是

  1. IESI Collections
  2. PowerCollections
  3. C5

答案 6 :(得分:0)

只是对其他评论的一点点补充。如果您需要对其他客户列表进行排序,您可以使用SortedList。

答案 7 :(得分:0)

Hashset工作也很棒。

new HashSet<CustomObject>().Join()