为什么列表< t> .contains()太慢了?
我有一个对象列表,我想通过删除某些具有ids
的对象来过滤列表,即单独的列表中,即
List<Vehicle> vehicles; //All Vehicles List (260 vehicles data)
List<int> vehiclesIds; //Ids List to remove from Original List (Length < 260)
现在使用removeall() >它采用Asound
25到30秒
。
vehicles.RemoveAll(e => vehiclesIds.Contains(e.Id));
但是,如果我将用于循环
,则仅需8至20毫秒
。
foreach (var vehiclesId in vehiclesIds)
{
vehicles.RemoveAll(e=> vehiclesId == e.Id);
}
我多次运行此代码,并在使用stopwatch
list.contains()
是进行缓慢处理的原因。
I have a list of objects and I want to filter the list by removing some objects that have ids
present in a separate list i.e.
List<Vehicle> vehicles; //All Vehicles List (260 vehicles data)
List<int> vehiclesIds; //Ids List to remove from Original List (Length < 260)
Now for removing if i'm using RemoveAll()
it takes areound 25 to 30 seconds
.
vehicles.RemoveAll(e => vehiclesIds.Contains(e.Id));
But if I'm using for loop
as the following it takes only 8 to 20 milliseconds
.
foreach (var vehiclesId in vehiclesIds)
{
vehicles.RemoveAll(e=> vehiclesId == e.Id);
}
I multiple times run this code and analyse this after using StopWatch
that List.Contains()
is the reason for slow processing.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这两个版本之间的逻辑不同。
第一个版本首先循环车辆,寻找ID中的比赛。
包含
使用默认比较,这可能是一种缓慢的比较方式,因为它使用了接口。您可以使用
hashset&lt;
查找匹配ID来改进此版本。这应该更快(即使它也使用包含
),因为它可以内部使用HashTable。第二个版本首先循环较小的ID列表。您可以通过使用
字典
为车辆
来改进此版本,我想这是最后一个版本是最快的。
The logic between these two versions is different.
The first version loops the vehicles first, looking for matches in the IDs.
Contains
uses the default comparer, which might be a slow way of comparing because it uses interfaces.You can improve this version by using a
HashSet<int>
to find matching IDs. This should be faster (even though it also usesContains
) as it uses a hashtable internally.The second version instead loops the smaller list of IDs first. You can improve this version by using a
Dictionary
for thevehicles
i would imagine this last version to be the fastest.
TLDR:您问题的答案“为什么list.contains()太慢?”是:不是。您没有向我们展示的其他地方一定有问题。
更长的答案:
第一个版本应该更快,因为它仅在列表中删除一次而不是多次删除元素。 (事实并不能更快地指向其他地方的某些问题。)
但是,第一个版本确实调用了
eartilesIds.contains(e.id)(e.id)
每辆车一次,这是O(n)手术。您可以通过从车辆ID中创建
HashSet&gt;
来改进它,然后将其用于查找。我尝试了三种方法(您的两种方法
hashset
One):我在PC上获得的结果如下:
如您所见,使用第一个版本明显比第二个版本要快得多。版本(我预期),但是使用
HashSet
甚至更快。我们必须得出的结论是,您看到的放缓是由于您没有向我们展示的代码。
TLDR: The answer to your question "Why List.Contains() is too slow?" is: It isn't. There must be something wrong elsewhere that you haven't shown us.
Longer answer:
The first version should be faster because it's only removing elements from the list once rather than multiple times. (The fact that it isn't faster points to some problem elsewhere.)
However, the first version does call
vehiclesIds.Contains(e.Id)
once for each vehicle, which is an O(N) operation.You could improve that by creating a
HashSet<int>
from the vehicle IDs and then use that for the lookup.I tried the three approaches (your two plus the
HashSet
one) in a benchmark:The results I obtained on my PC were as follows:
As you can see, using your first version is significantly faster than your second version (as I expected), but using a
HashSet
is even faster.The conclusion that we must draw is that the slowdown you're seeing is due to code that you haven't shown us.