List.Sort的效率是两倍,而List.Clone&分类

时间:2012-07-20 18:56:06

标签: c# .net performance sorting

语言细节:C#.NET 3.5 / 4.0; project是一个预编译的DLL,是其他产品调用/使用的“模块”。

我的问题是关于整体效率,我意识到这可能归结为“内存使用与CPU周期”的决定,这很好 - 我仍然想知道你认为哪条路线更好。

我有一个传递给方法的MyObjects列表,该方法需要按Property2对List进行排序,用它做“一些东西”,然后按Property1对List进行排序以做“其他事情”&继续生活。重要提示:当列表首次进入方法时(例如,来自数据层),列表已经由 Property1订购。

排序将是“自定义内联”,如下所示:

myList.Sort((ObjA, ObjB) => ObjA.Prop2.CompareTo(ObjB.Prop2));

这两个排序是一个好主意吗?或者,将列表克隆到新的ListB并且仅调用Sort一次(在ListB上,由Prop2调用)会更好吗?然后用它做“一些东西”,完成后,使用原始列表中的“其他东西”&继续。

我最初的猜测是“Two Sorts”会旋转更多CPU周期,而“Clone& Sort”会使用更多内存(因为它必须创建新的ListB对象) - 是的我知道列表成员(MyObjects)不会被克隆,它们只是被新的ListB指向。

思想?

2 个答案:

答案 0 :(得分:7)

制作新的List<T>将是O(n)操作,因为每个项目都会被复制到新列表中。 List<T>.Sort 通常是 O(n log n)

因此,排序两次会更慢。复制将需要您的列表副本。这是记忆与速度的关系。

话虽这么说,复制不会改变原始列表的排序顺序 - 在我看来,这是一个很大的优势,因为将列表传递给方法并让它返回更改通常是以后的错误来源因为人们不一定期望一种方法来改变你的订单。当您的列表已经排序时尤其如此 - 如果您遇到创建有序列表的麻烦,我建议尽可能避免更改该订单。

但是,根据您正在做的事情,您可以使用Enumerable.OrderBy按顺序取出第二组,并执行您的“内容”。这也与副本具有相同的优点,因为它不会改变原始列表的顺序。

答案 1 :(得分:2)

我会处理myList.OrderBy(w=>w.Prop2)的输出,然后我只使用原始列表,因为OrderBy不具有破坏性。