LINQ Ring: Any () vs Contains () untuk Koleksi Besar

103

Dengan banyaknya koleksi objek, apakah ada perbedaan performa antara berikut ini?

Collection. Berisi :

myCollection.Contains(myElement)

Enumerable.Any :

myCollection.Any(currentElement => currentElement == myElement)
SDReyes
sumber
7
Koleksi 10'000.000 int. Pemenangnya adalah konten untuk 300%. tetapi ada baiknya untuk mempertimbangkan varian yang disebutkan di bawah ini.
SDReyes
1
Ini tampaknya menunjukkan kontras yang mencolok antara keduanya: thedailywtf.com/Articles/State-of-the-UNION.aspx
David Peterson

Jawaban:

143

Contains()adalah metode instance, dan kinerjanya sangat bergantung pada koleksi itu sendiri. Misalnya, Contains()pada a Listadalah O (n), sedangkan Contains()pada a HashSetadalah O (1).

Any()adalah metode ekstensi, dan hanya akan melalui koleksi, menerapkan delegasi pada setiap objek. Oleh karena itu, ia memiliki kompleksitas O (n).

Any()lebih fleksibel namun karena Anda dapat mengoper delegasi. Contains()hanya dapat menerima suatu objek.

Etienne de Martel
sumber
27
Containsjuga merupakan metode ekstensi terhadap IEnumerable<T>(meskipun beberapa koleksi memiliki Containsmetode contoh sendiri juga). Seperti yang Anda katakan, Anylebih fleksibel daripada Containskarena Anda bisa meneruskan predikat khusus, tetapi Contains mungkin sedikit lebih cepat karena tidak perlu melakukan pemanggilan delegasi untuk setiap elemen.
LukeH
1
Apakah Any () melakukan operasi pada semua objek dalam koleksi atau diakhiri dengan kecocokan pertama?
Quarkly
1
Setidaknya menurut sumber , itu berhenti di pertandingan pertama. All()beroperasi dengan cara yang sama.
Etienne de Martel
13

Itu tergantung pada koleksinya. Jika Anda memiliki koleksi yang dipesan, makaContains mungkin melakukan pencarian cerdas (biner, hash, b-tree, dll.), Sedangkan dengan `Any () Anda pada dasarnya terjebak dengan enumerasi sampai Anda menemukannya (dengan asumsi LINQ-to-Objects) .

Perhatikan juga bahwa dalam contoh Anda, Any()menggunakan ==operator yang akan memeriksa persamaan referensial, sementara Containsakan menggunakan IEquatable<T>atau Equals()metode, yang mungkin ditimpa.

tster
sumber
4
Dengan .Any, Anda dapat dengan mudah membandingkan properti. Dengan. Berisi Anda bisa membandingkan objek dan Anda memerlukan IEqualityComparer tambahan untuk membandingkan properti.
msfanboy
1
@msfanboy: Itu benar, tetapi pertanyaannya secara khusus tentang kinerja dan menunjukkan perbandingan keseluruhan objek. Jadi menurut saya itu tidak relevan di sini.
tster
4

Saya kira itu akan tergantung pada jenis myCollectionis yang menentukan bagaimana Contains()diimplementasikan. Jika pohon biner diurutkan misalnya, itu bisa mencari lebih pintar. Juga dapat memperhitungkan hash elemen. Any()di sisi lain akan melakukan pencacahan melalui koleksi sampai elemen pertama yang memenuhi kondisi ditemukan. Tidak ada pengoptimalan jika objek memiliki metode pencarian yang lebih cerdas.

Jeff Mercado
sumber
0

Contains () juga merupakan metode ekstensi yang dapat bekerja cepat jika Anda menggunakannya dengan cara yang benar. Misalnya:

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

Ini akan memberikan kueri

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

sedangkan Any () di sisi lain selalu melakukan iterasi melalui O (n).

Semoga ini berhasil ....

Uwais
sumber