【问题标题】:List.Sort IComparer performanceList.Sort IComparer 性能
【发布时间】:2010-10-30 04:01:39
【问题描述】:

我正在尝试对一对 int 数组进行排序 (int[] a; int[] b;)

如果我使用 Array.Sort(a,b) 则性能非常好。

但是,我更喜欢使用 List 并将 int 对加载到结构中。 我可以使用带有重载的 Array.Sort() 使其工作,该重载为结构提供了一个简单的比较器,但它比 Array.Sort(a,b) 慢 4 倍

这正常吗?

【问题讨论】:

  • (注意为 IComparable 添加指标的已编辑答案)
  • 我想 List.Sort 和 Array.Sort 都使用了快速排序,这意味着性能差异的原因必须是访问元素的方式。
  • 是的。两者都使用快速排序。 List.Sort 比常规数组慢一点,但与排序值对的区别没有什么不同。

标签: arrays list sorting icomparer


【解决方案1】:

这听起来很现实;您正在引入更多复杂性(更多查找等、更多虚拟方法、更多范围检查),因此它只会变得更慢(数组访问非常直接且非常快速)。

看起来你可以通过实现IComparer<T>而不是委托方法来更快地获得它(但不如数组快); (edit) 并再次使用 IComparable<T> 更快:

Array.Sort: 2241ms
List.Sort (delegate): 8714ms
List.Sort (interface): 6976ms
List.Sort (comparable): 5456ms

带代码:

using System;
using System.Collections.Generic;
using System.Diagnostics;

struct MyStruct : IComparable<MyStruct>
{
    private readonly int key, value;
    public int Key { get { return key; } }
    public int Value { get { return value; } }
    public MyStruct(int key, int value)
    {
        this.key = key;
        this.value = value;
    }
    public int CompareTo(MyStruct other)
    {
        return key.CompareTo(other.key);
    }
}
static class Program
{
    static void Main()
    {
        const int SIZE = 10000000;
        int[] a = new int[SIZE], b = new int[SIZE];
        Random rand = new Random();
        for(int i = 0 ; i < SIZE ; i++) {
            a[i] = rand.Next();
            b[i] = i;
        }
        var list = new List<MyStruct>(SIZE);
        for (int i = 0; i < SIZE; i++)
        {
            list.Add(new MyStruct(a[i], b[i]));
        }
        var list2 = new List<MyStruct>(list);
        var list3 = new List<MyStruct>(list);

        var watch = Stopwatch.StartNew();
        Array.Sort(a, b);
        watch.Stop();
        Console.WriteLine("Array.Sort: " + watch.ElapsedMilliseconds + "ms");

        watch = Stopwatch.StartNew();
        list.Sort((x, y) => x.Key.CompareTo(y.Key));
        watch.Stop();
        Console.WriteLine("List.Sort (delegate): " + watch.ElapsedMilliseconds + "ms");

        watch = Stopwatch.StartNew();
        list2.Sort(MyComparer.Default);
        watch.Stop();
        Console.WriteLine("List.Sort (interface): " + watch.ElapsedMilliseconds + "ms");

        watch = Stopwatch.StartNew();
        list3.Sort();
        watch.Stop();
        Console.WriteLine("List.Sort (comparable): " + watch.ElapsedMilliseconds + "ms");
    }
    sealed class MyComparer : IComparer<MyStruct>
    {
        private MyComparer() { }
        public static readonly MyComparer Default = new MyComparer();
        public int Compare(MyStruct x, MyStruct y)
        {
            return x.Key.CompareTo(y.Key);
        }
    }
}

【讨论】:

  • 干杯。谢谢马克。不确定我能否忍受性能损失,因此可能会按照 List 类的方式编写一些可以在幕后使用 Array.Sort 的内容。
  • 真正的诀窍是使用 IComparable 而不仅仅是从非泛型 IComparable 派生。这样比较就不必从Object中确定类型了。
  • @fmuecke 在许多情况下,泛型并不是很有用(尤其是涉及数据绑定或反射的任何事情);但是,在此处的示例中,它使用通用 API...
猜你喜欢
  • 2019-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多