В чем разница между HashSet и List?


можете ли вы объяснить, в чем разница между HashSet<T> и List<T> в .Чистая?

может быть, вы можете объяснить на примере, в каких случаях HashSet<T> должно быть предпочтительным в отношении List<T> ?

спасибо.

8 139

8 ответов:

в отличие от списка ...

  1. HashSet-это список без повторяющихся членов.

  2. поскольку хэш-набор ограничен только уникальными записями, внутренняя структура оптимизирована для поиска (по сравнению со списком) - это значительно быстрее

  3. добавление в HashSet возвращает логическое значение-false, если добавление не удается из-за уже существующего в Set .) Может выполнять математические операции над множеством: Соединение / пересечение / Issubset etc.

  4. HashSet не реализует IList только ICollection

  5. вы не можете использовать индексы с хэш-набором, только перечислители.

основной причиной использования хэш-набора было бы, если вы заинтересованы в выполнении операций набора.

учитывая 2 набора: hashSet1 и hashSet2

 //returns a list of distinct items in both sets
 HashSet set3 = set1.Union( set2 );

летит по сравнению с эквивалентной операцией с использованием LINQ. Это тоже аккуратнее пиши!

A HashSet<T> Это класс, предназначенный, чтобы дать вам O(1) поиск для сдерживания (т. е. содержит ли эта коллекция конкретный объект, и скажите мне ответ быстро).

A List<T> это класс, предназначенный, чтобы дать вам коллекцию с O(1) произвольный доступ, Чем может расти динамически (думаю, динамический массив). Вы можете проверить сдерживание в O(n) время (если список не отсортирован, то вы можете сделать двоичный поиск в O(log n) времени).

может быть, вы можете объяснить с примером в каких случаях HashSet<T> должно быть предпочтительным в отношении List<T>

когда вы хотите проверить включение в O(1).

чтобы быть более точным, давайте продемонстрируем на примерах,

вы не можете использовать HashSet, как в следующем примере.

HashSet<string> hashSet1 = new HashSet<string>(){"1","2","3"};
for (int i = 0; i < hashSet1.Count; i++)
    Console.WriteLine(hashSet1[i]);

hashSet1[i] приведет к ошибке:

невозможно применить индексирование с [] к выражению типа - Система.Коллекции.Родовой.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 etc.

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

кстати, порядка нет сохраняется в хэш-наборах. В примере мы добавили элемент " 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

использовать List<T> Если вы хотите:

  • хранить коллекцию предметов в определенном порядке.

если вы знаете индекс элемента, который вы хотите (а не от стоимости самого товара) поиск O(1). Если вы не знаете индекс, поиск элемента занимает больше времени,O(n) для сбора несортированных.

использовать Hashset<T> Если вы хотите:

  • быстро выяснить, если определенный объект содержится в a коллекция.

если вы знаете имя вещи, которую вы хотите найти, поиск O(1) (это " хэш " часть). Он не поддерживает порядок, как List<T> делает, и вы не можете хранить дубликаты (добавление дубликата не имеет никакого эффекта, это часть "Set").

пример использования Hashset<T> было бы, если вы хотите узнать, если слово играл в игре Эрудит является действительным словом на английском языке (или на другом языке). Еще лучше было бы, если бы вы хотели построить веб-сервис, который будет использоваться всеми экземплярами онлайн-версии такой игры.

A List<T> было бы хорошей структурой данных для создания табло для отслеживания результатов игрока.

список-это упорядоченный список. Это

  • доступ по целочисленному индексу
  • может содержать дубликаты
  • имеет предсказуемый порядок

HashSet-это набор. Это:

  • может блокировать повторяющиеся элементы (см. Добавить(T))
  • не гарантирует порядок элементов в наборе
  • имеет операции, которые вы ожидали бы на множестве,например, IntersectWith, IsProperSubsetOf, Союз с ним.

список более подходит, когда вы хотите получить доступ к вашей коллекции, как если бы она была похожа на массив, к которому вы можете добавлять, вставлять и удалять элементы. HashSet является лучшим выбором, если вы хотите рассматривать свою коллекцию как "мешок" элементов, в котором порядок не важен или когда вы хотите сравнить его с другими наборами, используя такие операции, как IntersectWith или UnionWith.

список представляет собой упорядоченную коллекцию объектов типа T, которые в отличие от массива можно добавлять и удалять записи.

вы бы использовали список, в котором вы хотите ссылаться на членов в порядке их хранения, и вы обращаетесь к ним по позиции, а не к самому элементу.

HashSet похож на словарь, что сам элемент является ключом, а также Значение, порядок не гарантируется.

вы бы использовали хэш-набор, где вы хотите проверить это объект находится в коллекции

список не обязательно уникален, в то время как hashset, для одного.

Если вы решите применить эти структуры данных для фактического использования в разработке, управляемой данными, хэш-набор очень полезен при тестировании репликации с источниками адаптера данных, для очистки данных и миграции.

кроме того, при использовании класса DataAnnotations можно реализовать ключевую логику в свойствах класса и эффективно управлять естественным индексом (кластеризованным или нет) с помощью хэш-набора, где это было бы очень сложно в реализации списка.

сильный вариант для использования список предназначен для реализации универсальных средств для нескольких сред в модели представления, таких как отправка списка классов в представление MVC для помощника DropDownList, а также для отправки в виде конструкции JSON через WebApi. Список позволяет использовать типичную логику сбора классов и сохраняет гибкость для более "интерфейсного" подхода к вычислению одной модели представления для разных сред.