Можете ли вы объяснить, в чем разница между HashSet<T>
и List<T>
в .NET?
Может быть, вы можете объяснить на примере, в каких случаях HashSet<T>
следует отдавать предпочтение List<T>
?
Можете ли вы объяснить, в чем разница между HashSet<T>
и List<T>
в .NET?
Может быть, вы можете объяснить на примере, в каких случаях HashSet<T>
следует отдавать предпочтение List<T>
?
Ответы:
В отличие от списка <> ...
HashSet - это список без повторяющихся членов.
Поскольку HashSet ограничен, чтобы содержать только уникальные записи, внутренняя структура оптимизирована для поиска (по сравнению со списком) - это значительно быстрее
Добавление в HashSet возвращает логическое значение - false, если добавление не выполняется из-за того, что оно уже существует в Set
Может выполнять математические операции над множествами: объединение / пересечение / 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, пока List позволяет вам это делать, и когда вы добавляете элемент в 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, допустимым словом на английском (или другом языке). Еще лучше было бы, если бы вы хотели создать веб-сервис, который будет использоваться всеми экземплярами онлайн-версии такой игры.
A List<T>
была бы хорошей структурой данных для создания табло для отслеживания результатов игрока.
Список - это упорядоченный список. это
HashSet - это набор. Это:
Список более уместен, когда вы хотите получить доступ к своей коллекции, как если бы она была похожа на массив, к которому вы могли бы добавлять, вставлять и удалять элементы. HashSet - лучший выбор, если вы хотите относиться к своей коллекции как к «сумке» предметов, порядок которых не важен, или когда вы хотите сравнить ее с другими наборами, используя такие операции, как IntersectWith или UnionWith.
Список не обязательно уникален, в то время как hashset для одного.
Список - это упорядоченная коллекция объектов типа T, в отличие от массива, вы можете добавлять и удалять записи.
Вы бы использовали список, в котором вы хотите ссылаться на участников в том порядке, в котором вы их сохранили, и вы получаете к ним доступ по позиции, а не по самому элементу.
HashSet похож на словарь, в котором сам элемент является ключом и значением, порядок не гарантируется.
Вы бы использовали HashSet, где вы хотите проверить, что объект находится в коллекции
List
поддерживает порядок (то есть, когда вещи были добавлены), но не сортирует элементы автоматически. Вам придется позвонить .Sort
или использовать SortedList
.
Если вы решите применить эти структуры данных для фактического использования в разработке, управляемой данными, HashSet ОЧЕНЬ будет полезен при тестировании репликации на источники адаптеров данных, для очистки и переноса данных.
Кроме того, при использовании класса DataAnnotations можно реализовать логику Key для свойств класса и эффективно управлять естественным индексом (кластеризованным или нет) с помощью HashSet, где это будет очень трудно реализовать в List.
Сильным вариантом использования списка является реализация универсальных шаблонов для нескольких сред в модели представления, например, отправка списка классов в MVC-представление для помощника DropDownList, а также для отправки в виде конструкции JSON через WebApi. Этот список допускает типичную логику сбора классов и сохраняет гибкость для подхода, более похожего на «интерфейс», для вычисления модели одного представления для различных сред.