Враховуючи величезну колекцію об'єктів, чи є різниця в продуктивності між наступними?
myCollection.Contains(myElement)
Численні .
myCollection.Any(currentElement => currentElement == myElement)
Враховуючи величезну колекцію об'єктів, чи є різниця в продуктивності між наступними?
myCollection.Contains(myElement)
Численні .
myCollection.Any(currentElement => currentElement == myElement)
Відповіді:
Contains()
є методом екземпляра, і його ефективність багато в чому залежить від самої колекції. Наприклад, Contains()
на a List
є O (n), а Contains()
на a HashSet
- O (1).
Any()
є методом розширення і буде просто проходити колекцію, застосовуючи делегат на кожен об'єкт. Тому він має складність O (n).
Any()
але більш гнучка, оскільки ви можете передати делегата. Contains()
може прийняти лише об’єкт.
Contains
також є методом розширення проти IEnumerable<T>
(хоча деякі колекції також мають власний Contains
метод екземпляра). Як ви кажете, Any
це гнучкіше, ніж Contains
через те, що ви можете передати його спеціальним предикатом, але Contains
може бути трохи швидшим, оскільки йому не потрібно виконувати виклик делегата для кожного елемента.
All()
діє аналогічно.
Це залежить від колекції. Якщо у вас є впорядкована колекція, Contains
ви можете зробити інтелектуальний пошук (двійковий, хеш, b-дерево тощо), тоді як з пунктом `Any () ви в основному затримані до перерахування, поки не знайдете його (припускаючи LINQ-to-Objects) .
Також зауважте, що у вашому прикладі Any()
використовується ==
оператор, який перевірятиме референтну рівність, в той час як Contains
буде використовуватись IEquatable<T>
або Equals()
метод, який може бути замінений.
Я вважаю, що це залежатиме від типу того myCollection
, що диктує, як Contains()
реалізується. Якщо, наприклад, відсортовано двійкове дерево, воно може шукати розумніші. Також він може враховувати хеш елементів. Any()
з іншого боку буде перераховуватися через колекцію, поки не буде знайдений перший елемент, що задовольняє умові. Немає оптимізацій щодо того, якби об’єкт мав розумніший спосіб пошуку.
Містить () - це також метод розширення, який може швидко працювати, якщо використовувати його правильно. Наприклад:
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).
Сподіваюся, це спрацює….