我正在寻找一种高效的方法将第二个ICollection中不同的项添加到现有的ICollection中。我使用的是.NET 4。
我正在寻找一种高效的方法将第二个ICollection中不同的项添加到现有的ICollection中。我使用的是.NET 4。
list1.Union(list2).Distinct(aCustomComparer).ToList()
var union = firstCollection.Union(secondCollection);
这将使用默认的相等比较,对于大多数对象来说是引用相等。要更改此设置,您可以为集合中的项类型定义一个IEqualityComparer通用类,执行更语义化的比较,并将其指定为Union的第二个参数。
另一种添加到您现有列表的方法是:
list1.AddRange(list2.Distinct().Except(list1));
var union = firstCollection.Union(secondCollection);
MethodA:1ms
MethodB:2827ms
然而 - 必须将该IEnumerable转换为其他类型的集合,例如List<>(如ADas发布的版本)会改变一切:
只需在MethodA中添加.ToList()即可。
var union = firstCollection.Union(secondCollection).ToList();
改变结果:
方法A:3656毫秒
方法B:2803毫秒
所以,似乎需要更多了解你所处理的具体情况,并且任何解决方案都应该经过测试,因为一个小的(代码)改变可能会产生巨大的影响。
以下是我用来比较这些方法的测试 - 我确定这是一种愚蠢的测试方式 - 但它似乎有效 :)
private static void Main(string[] args)
{
ICollection<string> collectionA = new List<string>();
ICollection<string> collectionB = new List<string>();
for (int i = 0; i < 1000; i++)
{
string randomString = Path.GetRandomFileName();
collectionA.Add(randomString);
collectionA.Add(randomString);
collectionB.Add(randomString);
collectionB.Add(randomString);
}
Stopwatch testA = new Stopwatch();
testA.Start();
MethodA(collectionA, collectionB);
testA.Stop();
Stopwatch testB = new Stopwatch();
testB.Start();
MethodB(collectionA, collectionB);
testB.Stop();
Console.WriteLine("MethodA: {0}ms", testA.ElapsedMilliseconds);
Console.WriteLine("MethodB: {0}ms", testB.ElapsedMilliseconds);
Console.ReadLine();
}
private static void MethodA(ICollection<string> collectionA, ICollection<string> collectionB)
{
for (int i = 0; i < 10000; i++)
{
var result = collectionA.Union(collectionB);
}
}
private static void MethodB(ICollection<string> collectionA, ICollection<string> collectionB)
{
for (int i = 0; i < 10000; i++)
{
var result = new HashSet<string>(collectionA);
foreach (string s in collectionB)
{
result.Add(s);
}
}
}
Union
使用默认的相等比较器,具体取决于类型是否为引用比较器。请参阅 https://msdn.microsoft.com/en-us/library/vstudio/bb341731(v=vs.100).aspx 和 https://msdn.microsoft.com/en-us/library/vstudio/bb341731(v=vs.100).aspx。此外,正如您所提到的,最好为Union
方法提供自定义比较器,从而消除Distinct
调用以提高可读性和(可能?)轻微的性能提升。 - Igor Pashchuk