LINQ Ring: Any () เทียบกับ () สำหรับคอลเลกชันขนาดใหญ่


103

เนื่องจากวัตถุจำนวนมากมีความแตกต่างด้านประสิทธิภาพระหว่างสิ่งต่อไปนี้หรือไม่?

คอลเลกชันประกอบด้วย :

myCollection.Contains(myElement)

นับได้ใด ๆ :

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

7
คอลเลกชันของ 10'000.000 ของ int ผู้ชนะจะได้รับ 300% แต่ควรพิจารณาความแปรปรวนที่กล่าวถึงด้านล่าง
SDReyes

1
สิ่งนี้ดูเหมือนจะแสดงความแตกต่างอย่างสิ้นเชิงระหว่างทั้งสอง: thedailywtf.com/Articles/State-of-the-UNION.aspx
David Peterson

คำตอบ:


143

Contains()เป็นวิธีการอินสแตนซ์และประสิทธิภาพของมันขึ้นอยู่กับคอลเลกชันเป็นส่วนใหญ่ ตัวอย่างเช่นContains()บน a Listคือ O (n) ในขณะที่Contains()บนHashSetคือ O (1)

Any()เป็นวิธีการขยายและจะดำเนินการรวบรวมโดยใช้ผู้รับมอบสิทธิ์กับทุกออบเจ็กต์ ดังนั้นจึงมีความซับซ้อนของ O (n)

Any()มีความยืดหยุ่นมากขึ้นอย่างไรก็ตามเนื่องจากคุณสามารถส่งตัวแทนได้ Contains()ยอมรับได้เฉพาะวัตถุ


27
Containsยังเป็นวิธีการต่อขยายIEnumerable<T>(แม้ว่าบางคอลเลกชันจะมีContainsวิธีการอินสแตนซ์ของตัวเองด้วย) อย่างที่คุณพูดAnyมีความยืดหยุ่นมากกว่าContainsเพราะคุณสามารถส่งผ่านเพรดิเคตที่กำหนดเองได้ แต่Contains อาจเร็วกว่าเล็กน้อยเนื่องจากไม่จำเป็นต้องดำเนินการร้องขอตัวแทนสำหรับแต่ละองค์ประกอบ
LukeH

1
ไม่ใด ๆ ()ดำเนินการเกี่ยวกับวัตถุทั้งหมดในคอลเลกชันหรือไม่ก็บอกเลิกกับการแข่งขันครั้งแรก?
Quarkly

1
อย่างน้อยตามแหล่งที่มาก็หยุดในนัดแรก All()ดำเนินการในทำนองเดียวกัน
Etienne de Martel

13

มันขึ้นอยู่กับคอลเลกชัน หากคุณมีคอลเลกชันที่สั่งซื้อContainsอาจทำการค้นหาแบบสมาร์ท (ไบนารีแฮช b-tree ฯลฯ ) ในขณะที่ `` Any () คุณติดอยู่กับการแจงนับจนกว่าจะพบ (สมมติว่า LINQ-to-Objects) .

โปรดทราบว่าในตัวอย่างของคุณAny()กำลังใช้ตัว==ดำเนินการซึ่งจะตรวจสอบความเท่าเทียมกันของการอ้างอิงในขณะที่Containsจะใช้IEquatable<T>หรือEquals()วิธีการซึ่งอาจถูกแทนที่


4
ด้วย. คุณสามารถเปรียบเทียบคุณสมบัติได้อย่างง่ายดาย ด้วย. ประกอบด้วยคุณสามารถเปรียบเทียบวัตถุและคุณต้องมี IEqualityComparer พิเศษเพื่อเปรียบเทียบคุณสมบัติ
msfanboy

1
@msfanboy: นั่นเป็นเรื่องจริง แต่คำถามเกี่ยวกับประสิทธิภาพโดยเฉพาะและแสดงให้เห็นถึงการเปรียบเทียบวัตถุทั้งหมด เลยไม่คิดว่าจะเกี่ยวข้องตรงนี้
tster

4

ฉันคิดว่ามันจะขึ้นอยู่กับประเภทของmyCollectionสิ่งที่กำหนดวิธีContains()การใช้งาน หากต้นไม้ไบนารีที่เรียงลำดับเป็นต้นก็สามารถค้นหาได้อย่างชาญฉลาด นอกจากนี้ยังอาจคำนึงถึงแฮชขององค์ประกอบด้วย Any()ในทางกลับกันจะแจกแจงผ่านคอลเลกชันจนกว่าจะพบองค์ประกอบแรกที่ตรงตามเงื่อนไข ไม่มีการปรับให้เหมาะสมหากวัตถุมีวิธีการค้นหาที่ชาญฉลาดกว่า


0

ประกอบด้วย () เป็นวิธีการขยายที่สามารถทำงานได้อย่างรวดเร็วหากคุณใช้อย่างถูกต้อง สำหรับเช่น:

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

สิ่งนี้จะให้แบบสอบถาม

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

ในขณะที่ Any () ในทางกลับกันจะวนซ้ำผ่าน O (n) เสมอ

หวังว่าจะได้ผล ....

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.