Можете чи ви пояснити , в чому різниця між HashSet<T>
і List<T>
в .NET?
Може, ви можете пояснити на прикладі, у яких випадках HashSet<T>
слід віддати перевагу List<T>
?
Можете чи ви пояснити , в чому різниця між HashSet<T>
і List<T>
в .NET?
Може, ви можете пояснити на прикладі, у яких випадках HashSet<T>
слід віддати перевагу List<T>
?
Відповіді:
На відміну від списку <> ...
HashSet - це список без повторюваних членів.
Оскільки HashSet обмежений вмістом лише унікальних записів, внутрішня структура оптимізована для пошуку (порівняно зі списком) - це значно швидше
Додавання до HashSet повертає логічне значення - false, якщо додавання не вдалося через вже наявне в Set
Може виконувати операції з математичним набором проти набору: Union / Intersection / IsSubsetOf і т.д.
HashSet не реалізує IList лише ICollection
Не можна використовувати індекси з HashSet, лише з перелічниками.
Основною причиною використання HashSet буде, якщо ви зацікавлені у виконанні операцій Set.
Дано 2 набори: hashSet1 і hashSet2
//returns a list of distinct items in both sets
HashSet set3 = set1.Union( set2 );
летить порівняно з еквівалентною операцією за допомогою LINQ. Це також акуратніше писати!
Union
методом. Я використовував UnionWith
замість цього.
Якщо точніше, давайте продемонструємо на прикладах,
Ви не можете використовувати HashSet, як у наступному прикладі.
HashSet<string> hashSet1 = new HashSet<string>(){"1","2","3"};
for (int i = 0; i < hashSet1.Count; i++)
Console.WriteLine(hashSet1[i]);
hashSet1[i]
призведе до помилки:
Неможливо застосувати індексацію за допомогою [] до виразу типу "System.Collections.Generic.HashSet"
Ви можете використовувати оператор foreach:
foreach (var item in hashSet1)
Console.WriteLine(item);
Ви не можете додати дублюючі елементи до HashSet, тоді як Список дозволяє це зробити, і поки ви додаєте елемент до HashSet, ви можете перевірити, чи він містить цей предмет чи ні.
HashSet<string> hashSet1 = new HashSet<string>(){"1","2","3"};
if (hashSet1.Add("1"))
Console.WriteLine("'1' is successfully added to hashSet1!");
else
Console.WriteLine("'1' could not be added to hashSet1, because it contains '1'");
HashSet має деякі корисні функції , такі як IntersectWith
, UnionWith
, IsProperSubsetOf
, ExceptWith
, і SymmetricExceptWith
т.д.
IsProperSubsetOf
:
HashSet<string> hashSet1 = new HashSet<string>() { "1", "2", "3", "4" };
HashSet<string> hashSet2 = new HashSet<string>() { "2", "4", "6", "8" };
HashSet<string> hashSet3 = new HashSet<string>() { "1", "2", "3", "4", "5" };
if (hashSet1.IsProperSubsetOf(hashSet3))
Console.WriteLine("hashSet3 contains all elements of hashSet1.");
if (!hashSet1.IsProperSubsetOf(hashSet2))
Console.WriteLine("hashSet2 does not contains all elements of hashSet1.");
UnionWith
:
HashSet<string> hashSet1 = new HashSet<string>() { "3", "4" };
HashSet<string> hashSet2 = new HashSet<string>() { "2", "4", "6", "8" };
hashSet1.UnionWith(hashSet2); //hashSet1 -> 3, 2, 4, 6, 8
IntersectWith
:
HashSet<string> hashSet1 = new HashSet<string>() { "3", "4", "8" };
HashSet<string> hashSet2 = new HashSet<string>() { "2", "4", "6", "8" }
hashSet1.IntersectWith(hashSet2);//hashSet1 -> 4, 8
ExceptWith
:
HashSet<string> hashSet1 = new HashSet<string>() { "1", "2", "3", "5", "6" };
HashSet<string> hashSet2 = new HashSet<string>() { "1", "2", "3", "4" };
hashSet1.ExceptWith(hashSet2);//hashSet1 -> 5, 6
SymmetricExceptWith
:
HashSet<string> hashSet1 = new HashSet<string>() { "1", "2", "3", "5", "6" };
HashSet<string> hashSet2 = new HashSet<string>() { "1", "2", "3", "4" };
hashSet1.SymmetricExceptWith(hashSet2);//hashSet1 -> 4, 5, 6
До речі, порядок не зберігається в HashSets. У прикладі ми додали останній елемент "2", але це у другому порядку:
HashSet<string> hashSet1 = new HashSet<string>() { "3", "4", "8" };
hashSet1.Add("1"); // 3, 4, 8, 1
hashSet1.Remove("4"); // 3, 8, 1
hashSet1.Add("2"); // 3, 2 ,8, 1
A HashSet<T>
- клас, призначений для того, щоб дати вам O(1)
пошук вмісту (тобто чи містить ця колекція конкретний об'єкт, і швидко скажіть мені відповідь).
A List<T>
- клас, призначений для отримання колекції з O(1)
випадковим доступом, ніж може динамічно зростати (подумайте про динамічний масив). Ви можете перевірити обмеження в O(n)
часі (якщо список не відсортований, ви можете O(log n)
вчасно виконати двійковий пошук ).
Можливо, ви можете пояснити на прикладі, у яких випадках
HashSet<T>
слід віддати перевагуList<T>
Коли ви хочете перевірити вміст в O(1)
.
Використовуйте, List<T>
коли ви хочете:
Якщо ви знаєте, індекс потрібного товару (а не значення самого елемента) - це пошук O(1)
. Якщо ви не знаєте індексу, для пошуку O(n)
несортованої колекції потрібен більше часу .
Використовуйте, Hashset<T>
коли ви хочете:
Якщо ви знаєте назву речі, яку ви хочете знайти, Lookup є O(1)
(це частина 'Hash'). Він не підтримує впорядкування, як List<T>
це, і ви не можете зберігати дублікати (додавання дубліката не має ефекту, це частина "Встановити").
Прикладом того, як використовувати a, Hashset<T>
було б, якщо ви хочете дізнатися, чи слово, яке грається в гру Scrabble, є дійсним словом англійською мовою (чи іншою мовою). Ще краще, якби ви хотіли створити веб-сервіс, який би використовувався всіма прикладами онлайн-версії такої гри.
Було List<T>
б гарною структурою даних для створення табло для відстеження результатів гравців.
Список - упорядкований список. це є
HashSet - це набір. Це:
Список більш доцільний, коли ви хочете отримати доступ до своєї колекції так, ніби це був масив, до якого ви могли додавати, вставляти та видаляти елементи. HashSet - кращий вибір, якщо ви хочете ставитися до своєї колекції як до «мішка» з предметами, в якому порядок не важливий, або коли ви хочете порівнювати його з іншими наборами, використовуючи такі операції, як IntersectWith або UnionWith.
Список необов’язково унікальний, тоді як хештет - для одного.
Список - це упорядкована колекція об'єктів типу T, які на відміну від масиву можна додавати та видаляти записи.
Ви б використовували список, де ви хочете посилатися на членів у порядку, коли ви їх зберігали, і ви отримуєте доступ до них за позицією, а не самим елементом.
HashSet - це як словник, що сам елемент є ключовим, а також значенням, впорядкованість не гарантується.
Ви б використовували HashSet там, де ви хочете перевірити, чи є об’єкт у колекції
List
підтримує замовлення (тобто коли речі були додані), але не сортує автоматично елементи. Вам доведеться зателефонувати .Sort
або скористатися SortedList
.
Якщо ви вирішили застосувати ці структури даних для фактичного використання в розробці, керованої даними, HashSet дуже корисний для тестування реплікації на джерела адаптера даних для очищення та міграції даних.
Крім того, якщо використовується клас DataAnnotations, можна реалізувати логіку Key щодо властивостей класу та ефективно керувати природним індексом (кластеризованим чи ні) за допомогою HashSet, де це буде дуже складно в реалізації списку.
Важливим варіантом використання списку є реалізація загальної інформації для кількох носіїв у моделі перегляду, наприклад, пересилання списку класів у MVC View для помічника DropDownList, а також для надсилання у вигляді конструкції JSON через WebApi. Список дозволяє використовувати типову логіку колекціонування класів і зберігає гнучкість для більш «інтерфейсного» підходу до обчислення однієї моделі перегляду для різних середовищ.