Hashset First()+ Remove()性能

时间:2017-09-10 16:35:03

标签: c# .net performance optimization hashset

我今天遇到了涉及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();
    }
}

1 个答案:

答案 0 :(得分:0)

如果您需要为hashset的每个条目执行某些操作,然后只删除条目,为什么不使用linq呢?

hashSet.ForEach(item => DoSomething(item, hashSet));
hashSet.Clear();

在处理大型集合时,这可能会让您获得可接受的性能。