LINQ Ring: Büyük Koleksiyonlar için Herhangi Biri () - İçerir ()


104

Büyük bir nesne koleksiyonu göz önüne alındığında, aşağıdakiler arasında bir performans farkı var mı?

Koleksiyon. İçerir :

myCollection.Contains(myElement)

Numaralandırılabilir.Herhangi bir :

myCollection.Any(currentElement => currentElement == myElement)

7
10.000.000 int'lerin bir koleksiyonu. kazanan,% 300 için içerir. ancak aşağıda belirtilen farklılıkları dikkate almaya değer.
SDReyes

1
Bu, ikisi arasında keskin bir tezat oluşturuyor gibi görünüyor: thedailywtf.com/Articles/State-of-the-UNION.aspx
David Peterson

Yanıtlar:


143

Contains()bir örnek yöntemdir ve performansı büyük ölçüde koleksiyonun kendisine bağlıdır. Örneğin, Contains()bir ilgili Listiken, O (n) olan Contains()bir ilgili HashSetO (1) 'dir.

Any()bir genişletme yöntemidir ve sadece koleksiyondan geçerek temsilciyi her nesneye uygular. Bu nedenle O (n) karmaşıklığına sahiptir.

Any()ancak bir delege geçebileceğiniz için daha esnektir. Contains()sadece bir nesneyi kabul edebilir.


27
Containsaynı zamanda karşı bir genişletme yöntemidir IEnumerable<T>(bazı koleksiyonların da kendi Containsörnek yöntemi olmasına rağmen ). Sizin de söylediğiniz gibi, ona özel bir yüklem geçirebileceğinizden Anydaha esnektir Contains, ancak biraz daha hızlı Contains olabilir çünkü her öğe için bir temsilci çağrısı gerçekleştirmesi gerekmez.
LukeH

1
Any () işlemi koleksiyondaki tüm nesneler üzerinde gerçekleştiriyor mu yoksa ilk eşleşmeyle mi sona eriyor?
Quarkly

1
En azından kaynağa göre ilk maçta durur. All()benzer şekilde çalışır.
Etienne de Martel

13

Koleksiyona göre değişir. Sıralı bir koleksiyonunuz varsa, Containsakıllı bir arama (ikili, karma, b-ağaç, vb.) Yapabilirsiniz, `` Herhangi biri () ile temelde onu bulana kadar numaralandırmaya bağlı kalırsınız (LINQ-to-Objects varsayarak) .

Ayrıca, örneğinizde, referans eşitliğini kontrol edecek operatörü Any()kullandığınızı, kullanırken veya yöntemi geçersiz kılınabileceğini unutmayın.==ContainsIEquatable<T>Equals()


4
.Any ile özellikleri kolayca karşılaştırabilirsiniz. .Contains ile nesneleri karşılaştırabilirsiniz ve özellikleri karşılaştırmak için fazladan bir IEqualityComparer'a ihtiyacınız vardır.
msfanboy

1
@msfanboy: Bu doğru, ama soru özellikle performansla ilgiliydi ve tüm nesneyi karşılaştırmayı gösterdi. Bu yüzden bunun burada alakalı olduğunu düşünmüyorum.
tster

4

Sanırım bu, myCollectionnasıl Contains()uygulandığını belirleyen şeyin türüne bağlı olacaktır . Örneğin sıralı bir ikili ağaç ise daha akıllıca arama yapabilir. Ayrıca elemanın hash değerini de hesaba katabilir. Any()Öte yandan, koşulu karşılayan ilk öğe bulunana kadar koleksiyon boyunca numaralandırılacaktır. Nesnenin daha akıllı bir arama yöntemine sahip olup olmadığı konusunda hiçbir optimizasyon yoktur.


0

Contains (), doğru şekilde kullanırsanız hızlı çalışabilen bir genişletme yöntemidir. Örneğin:

var result = context.Projects.Where(x => lstBizIds.Contains(x.businessId)).Select(x => x.projectId).ToList();

Bu, sorguyu verecek

SELECT Id FROM Projects INNER JOIN (VALUES (1), (2), (3), (4), (5)) AS Data(Item) ON Projects.UserId = Data.Item

Öte yandan, Any () ise her zaman O (n) ile yineleme yapar.

Umarım bu işe yarar ....

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.