Vòng LINQ: Bất kỳ () so với Chứa () cho Bộ sưu tập khổng lồ


103

Với một bộ sưu tập đồ vật khổng lồ, có sự khác biệt về hiệu suất giữa các đồ vật sau đây không?

Bộ sưu tập. Nội dung :

myCollection.Contains(myElement)

Enumerable.Any :

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

7
Bộ sưu tập 10'000.000 của int. người chiến thắng là chứa 300%. nhưng nó đáng để xem xét các phương sai được đề cập bên dưới.
SDReyes

1
Điều này dường như cho thấy một sự tương phản rõ rệt giữa hai: thedailywtf.com/Articles/State-of-the-UNION.aspx
David Peterson

Câu trả lời:


143

Contains()là một phương thức thể hiện và hiệu suất của nó phụ thuộc phần lớn vào chính bộ sưu tập. Ví dụ, Contains()trên a Listlà O (n), trong khi Contains()trên a HashSetlà O (1).

Any()là một phương thức mở rộng và sẽ đơn giản đi qua bộ sưu tập, áp dụng ủy nhiệm trên mọi đối tượng. Do đó, nó có độ phức tạp là O (n).

Any()tuy nhiên, linh hoạt hơn vì bạn có thể vượt qua một đại biểu. Contains()chỉ có thể chấp nhận một đối tượng.


27
Containscũng là một phương thức mở rộng chống lại IEnumerable<T>(mặc dù một số tập hợp cũng có Containsphương thức phiên bản riêng của chúng ). Như bạn nói, Anylinh hoạt hơn Containsvì bạn có thể chuyển cho nó một vị từ tùy chỉnh, nhưng Contains thể nhanh hơn một chút vì nó không cần thực hiện lời gọi đại biểu cho mỗi phần tử.
LukeH

1
Liệu Any () có thực hiện thao tác trên tất cả các đối tượng trong bộ sưu tập hay nó kết thúc với trận đấu đầu tiên?
Hoàn toàn 14/02/19

1
Ít nhất theo nguồn tin , nó dừng ở trận đấu đầu tiên. All()hoạt động tương tự.
Etienne de Martel

13

Nó phụ thuộc vào bộ sưu tập. Nếu bạn có một bộ sưu tập có thứ tự, thì Containscó thể thực hiện tìm kiếm thông minh (nhị phân, băm, b-tree, v.v.), trong khi với `Any (), về cơ bản bạn gặp khó khăn với việc liệt kê cho đến khi tìm thấy nó (giả sử LINQ-to-Objects) .

Cũng lưu ý rằng trong ví dụ của bạn, Any()đang sử dụng ==toán tử sẽ kiểm tra sự bình đẳng tham chiếu, while Containssẽ sử dụng IEquatable<T>hoặc Equals()phương thức, có thể bị ghi đè.


4
Với .Any, bạn có thể dễ dàng so sánh các thuộc tính. Với .Contains, bạn chỉ có thể so sánh các đối tượng và bạn cần thêm IEqualityComparer để so sánh các thuộc tính.
msfanboy

1
@msfanboy: Đúng vậy, nhưng câu hỏi đặc biệt là về hiệu suất và cho thấy việc so sánh toàn bộ đối tượng. Vì vậy, tôi không nghĩ rằng nó có liên quan ở đây.
tster

4

Tôi cho rằng điều đó sẽ phụ thuộc vào loại myCollectionquy định cách Contains()thực hiện. Ví dụ, nếu một cây nhị phân được sắp xếp, nó có thể tìm kiếm thông minh hơn. Ngoài ra, nó có thể tính đến hàm băm của phần tử. Any()mặt khác sẽ liệt kê thông qua tập hợp cho đến khi tìm được phần tử đầu tiên thỏa mãn điều kiện. Không có tối ưu hóa nếu đối tượng có một phương pháp tìm kiếm thông minh hơn.


0

Contains () cũng là một phương thức mở rộng có thể hoạt động nhanh nếu bạn sử dụng nó đúng cách. Đối với ví dụ:

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

Điều này sẽ cung cấp cho truy vấn

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

trong khi bất kỳ () mặt khác luôn lặp qua O (n).

Hy vọng điều này sẽ hiệu quả ....

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.