我今天遇到了涉及hashset.remove的性能问题,我仍然不清楚问题是什么。我留下的问题是,为什么Approach2
方法明显快于Approach1
方法?我假设它是对HashSet.Remove的调用,但是MSDN文档说HashSet.Remove是O(1)。
public class HashSetTester
{
int TestNum = 20000;
public void Run()
{
var hashset2 = CreateTestHashSet();
var watch2 = new Stopwatch();
watch2.Start();
Approach2(hashset2);
watch2.Stop();
var hashset1 = CreateTestHashSet();
var watch1 = new Stopwatch();
watch1.Start();
Approach1(hashset1);
watch1.Stop();
Console.WriteLine("Approach1 is {0:0.0}x slower than Approach2", watch1.Elapsed.TotalSeconds / watch2.Elapsed.TotalSeconds);
}
HashSet<object> CreateTestHashSet()
{
var result = new HashSet<object>();
var rnd = new Random();
for (int i = 0; i < TestNum; i++)
{
result.Add(rnd.Next());
}
return result;
}
void Approach1(HashSet<object> hashset)
{
while (hashset.Any())
{
var instance = hashset.First();
hashset.Remove(instance);
DoSomething(instance, hashset);
}
}
void Approach2(HashSet<object> hashset)
{
var tempItems = new List<object>();
while (hashset.Any())
{
tempItems.Clear();
tempItems.AddRange(hashset);
hashset.Clear();
foreach (var instance in tempItems)
{
DoSomething(instance, hashset);
}
}
}
void DoSomething(object obj, HashSet<object> hashset)
{
// In some cases, hashset would be added to here
}
public static void Main()
{
new HashSetTester().Run();
}
}
答案 0 :(得分:0)
如果您需要为hashset的每个条目执行某些操作,然后只删除条目,为什么不使用linq呢?
hashSet.ForEach(item => DoSomething(item, hashSet));
hashSet.Clear();
在处理大型集合时,这可能会让您获得可接受的性能。