Является ли HashSet <T> таким же, как List <T>, но с уникальностью?
Мне нужно иметь возможность иметь уникальные элементы в коллекции.
Я собирался использовать словарь, чтобы использовать метод ContainsKey, но я думал, что это будет пустой тратой, поскольку я не буду использовать свойство Value пары Key/Value.
Я наткнулся на HashSet<T>
, который выглядит очень многообещающим. Единственное, что я могу найти, что я не могу найти в документах List<T>
, состоит в том, что HashSet<T>
является неупорядоченным. Я думаю, что все в порядке, я предполагаю, что это означает, что он не упорядочен, используя IEqualityComparer
. Пока порядок, в котором добавляются элементы, находится в одной и той же позиции индекса, я думаю, что это будет нормально, поскольку мне нужно выполнить повторную проверку, следовательно, хешсет, а затем проверить, что все записи являются последовательными.
Есть ли что-то еще, что я пропустил, сравнивая два типа?
Ответы
Ответ 1
Нет, важно HashSet<T>
не имеет понятия упорядочения или индексирования - в списке есть слоты 0.... n-1, тогда как набор является "просто набором".
Я думаю, что все в порядке, я предполагаю, что это означает, что он не упорядочен с использованием IEqualityComparer.
IEqualityComparer
не используется для заказа в любом случае - он говорит только о равенствах и хэш-кодах. HashSet<T>
не упорядочивается ни сравнением элементов (как, скажем, SortedSet<T>
), ни порядком размещения.
Пока порядок добавления элементов находится в одной позиции индекса, я думаю, что все будет хорошо.
Нет позиции индекса, и когда вы переходите через HashSet<T>
, нет гарантии, что вы вернете их в том порядке, в котором вы их добавили. Если вы даже думаете о заказе, HashSet<T>
не то, что вам нужно.
И снова все это также относится к Dictionary<TKey, TValue>
- вы также не должны делать никаких предположений о том, чтобы заказать его.
Ответ 2
Это "изображение" того, что выглядит как List<T>
:
List: |a|b|r|t|i|p|c|y|z|...
Index: |0|1|2|3|4|5|6|7|8|...
List<T>
представляет, ну, список элементов. Вы можете ссылаться на элемент по его позиции в списке.
Это "изображение" того, что выглядит как HashSet<T>
:
Set: |a|b|c| | | | | |i| | | | | | |p| |r| |t| | | | |y|z|
Bucket: |a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|
HashSet<T>
представляет набор уникальных элементов. У каждого предмета есть свое "ведро". Вы можете ссылаться на элемент по его ведро. Ведро, к которому принадлежит элемент, вычисляется непосредственно из элемента.
Одним из преимуществ использования HashSet
над a List
является поиск по постоянному времени. В List
элемент может находиться где угодно в List
, поэтому, чтобы найти его, вам нужно посмотреть на каждый элемент в List
. В HashSet
существует только одно возможное местоположение для любого данного элемента. Поэтому, чтобы искать элемент, все, что вам нужно сделать, это посмотреть в его ведро. Если он там, там, если нет, это не так.
Иллюстрации могут быть не на 100% точными (для простоты). Особенно пример HashSet
.
Ответ 3
Нет. A HashSet
не разрешает доступ через индекс, поскольку элементы arent упорядочены. Это не означает, как вы подозреваете, что они arent упорядочены в соответствии с некоторыми IEqualityComparer
. Это означает, что они не хранятся внутри хэш-набора в порядке их добавления.
Итак, если вам нужен контейнер для сохранения заказов или произвольного доступа, HashSet
не для вас.
Ответ 4
Похоже, это то, что вам нужно:
class UniqueList<T> : Collection<T>
{
protected override void InsertItem(int index, T item)
{
if (!base.Contains(item))
{
base.InsertItem(index, item);
}
else
{
// whatever
}
}
}
Вызов UniqueList.Add
добавит элемент в конец списка и не добавит повторяющиеся значения.
Ответ 5
Вы слегка ошибаетесь. Ни Dictionary
, ни HashSet
не сохраняет порядок элементов, это означает, что вы не можете положиться на индекс элемента. Теоретически вы можете использовать LINQ ElementAt()
для доступа к элементу по индексу, но снова обе коллекции не гарантируют сохранение этого порядка.
.NET предоставляет класс OrderedDictionary
, но он не является общим, поэтому у вас не будет безопасности типа во время компиляции. В любом случае он позволяет получать доступ к элементам по индексу.
Вот обычная реализация родового: OrderedDictionary (of T): общая реализация IOrderedDictionary. Ключевой момент: он сохраняет две коллекции - List
и Dictionary
одновременно; Список обеспечивает доступ по индексу и Dictionary
обеспечивает быстрый доступ с помощью ключа.
Ответ 6
Ну HashSet
концептуально является List
уникальных значений, но в отличие от List<T>
он фактически не реализует интерфейс IList
, а реализует ICollection
.
Кроме того, он имеет набор специальных функций, таких как:
Intersection
, IsSubsetOf
, IsSupersetOf
, Union,
, который List<T>
не имеет.
Эти функции, естественно, удобны при работе с несколькими HasSet
s.