Является ли 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.