2

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

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

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

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

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

做这两个排序是个好主意吗?或者,将列表克隆到一个新的 ListB 并且只调用一次排序(在 ListB 上,通过 Prop2)会更好吗?然后用它做“一些事情”,完成后,将原始列表用于“其他事情”并继续。

我最初的猜测是“两个排序”会旋转更多 CPU 周期,而“克隆和排序”会使用更多内存(因为它必须创建新的 ListB 对象)——是的,我知道 List 成员(MyObjects)会不会被克隆,它们只会被新的 ListB 指向。

想法?

4

2 回答 2

7

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

因此,排序两次会更慢。复制将需要您的清单的副本。这是内存与速度的权衡。

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

然而,根据你在做什么,你可以Enumerable.OrderBy按顺序拉出第二组,然后做你的“事情”。这也具有与副本相同的优点,因为它不会更改原始列表的顺序。

于 2012-07-20T19:00:17.050 回答
2

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

于 2012-07-20T19:00:27.607 回答