С# Установить коллекцию?

Кто-нибудь знает, есть ли хороший эквивалент коллекции Java Set в С#? Я знаю, что вы можете несколько имитировать набор, используя Dictionary или HashTable, заполняя, но игнорируя значения, но это не очень изящный способ.

Ответ 1

Попробуйте HashSet:

Класс HashSet (Of T) обеспечивает высокопроизводительные операции набора. Набор представляет собой набор, который не содержит повторяющихся элементов и элементы которого не имеют особого порядка...

Емкость объекта HashSet (Of T) - это количество элементов, которые может удерживать объект. Объем объекта HashSet (Of T) автоматически увеличивается по мере добавления элементов к объекту.

Класс HashSet (Of T) основан на модели математических наборов и обеспечивает высокопроизводительные операции набора, аналогичные доступу к клавишам Dictionary (Of TKey, TValue) или Hashtable. Проще говоря, класс HashSet (Of T) можно рассматривать как словарь (Of TKey, TValue) без значений.

Коллекция HashSet (Of T) не сортируется и не может содержать повторяющиеся элементы...

Ответ 2

Если вы используете .NET 3.5, вы можете использовать HashSet<T>. Это правда, что .NET не обслуживает множество, а также Java.

Wintellect PowerCollections также может помочь.

Ответ 3

Структура данных HashSet<T>:

Структура структуры библиотеки классов HashSet<T> была внедрена в .NET Framework 3.5. Полный список его членов можно найти на странице MSDN для HashSet<T>.

HashSet<T> более или менее смоделирован после математический набор, что означает, что:

  • Он не может содержать повторяющихся значений.

  • Его элементы не имеют особого порядка; поэтому тип не реализует интерфейс IList<T>, но более простой ICollection<T>. Как следствие, элементы внутри хэш-набора не могут быть случайно доступны через индексы; они могут быть перепрограммированы только через счетчик.

  • Доступны определенные функции набора, такие как Union, Intersection, IsSubsetOf, IsSupersetOf. Они могут пригодиться при работе с несколькими наборами.

Другим различием между HashSet<T> и List<T> является то, что вызов метода хеш-набора Add(item) возвращает логическое значение: true, если элемент был добавлен, и false в противном случае (поскольку он уже был найден в установлен).

Почему бы не List<T>?

Так как a HashSet<T> - это просто набор уникальных объектов, вы можете задаться вопросом, почему это должна быть структура данных. Обычный List<T> может иметь такое же поведение, проверяя, найден ли объект в списке, прежде чем добавлять его.

Короткий ответ - скорость. Поиск по нормальному List<T> очень быстро происходит очень быстро, так как добавляется больше элементов. A HashSet<T> требует конструкции структуры, которая будет обеспечивать быструю скорость поиска и вставки.

Ориентиры:

Сравним скорость работы HashSet<T> и List<T>.

Каждое исследование состояло из добавления целых чисел от 0 до 9999 в каждую коллекцию. Однако mod 25 применялся к каждому целому числу. Мод 25 делает максимальные типы элементов 25. Поскольку было добавлено 10 000 элементов, это вызвало 400 столкновений, что дало структурам данных возможность использовать их алгоритмы поиска. Время измерялось 3 раза после 10 000 испытаний и усреднялось.

Не уделяйте слишком много внимания конкретному времени работы тестов, поскольку они зависят от моего оборудования, но посмотрите, как они сравниваются друг с другом.

           Average time [ms]
----------------------------
HashSet<T>             2,290
List<T>                5,505

Теперь давайте создадим объекты вместо примитивных типов. Я написал быстрый Person класс с тремя полями: Name, LastName и ID. Поскольку я не использовал какой-либо конкретный способ сравнения объектов, все элементы будут добавлены без коллизий. На этот раз 1000 экземпляров Person были добавлены в каждую коллекцию для одного испытания. Общее время 3 комплектов 1000 испытаний было усреднено.

           Average time [ms]
----------------------------
HashSet<Person>          201
List<Person>           3,000

Как вы можете видеть, разница в времени работы становится астрономической при использовании объектов, что делает HashSet<T> выгодным.

Ответ 5

Я использую оболочку вокруг Dictionary<T, object>, сохраняя значения в значениях. Это дает O (1) добавлять, искать и удалять по клавишам, а для всех целей и задач действует как набор.

Ответ 6

Посмотрите PowerCollections в CodePlex. Помимо Set и OrderedSet, он имеет несколько других полезных типов коллекций, таких как Deque, MultiDictionary, Bag, OrderedBag, OrderedDictionary и OrderedMultiDictionary.

Для большего количества коллекций существует также C5 Generic Collection Library.

Ответ 7

Если вы используете .NET 4.0 или новее:

В случае, если вам нужна сортировка, используйте SortedSet<T>. В противном случае, если вы этого не сделаете, используйте HashSet<T>, так как он O(1) для поиска и управления операциями. Если SortedSet<T> - O(log n) для поиска и управления операциями.

Ответ 8

Через пару часов вы сможете реализовать свою работоспособную реализацию набора. Я использовал это, когда мне приходилось это делать (извините, у меня нет удобного кода): http://java.sun.com/j2se/1.4.2/docs/api/java/util/Set.html

Ответ 9

Я знаю, что это старый поток, но я столкнулся с той же проблемой и нашел HashSet очень ненадежным, потому что, учитывая одно и то же семя, GetHashCode() возвратил разные коды. Итак, я подумал, почему бы просто не использовать List и скрыть метод добавления, подобный этому

public class UniqueList<T> : List<T>
{
    public new void Add(T obj)
    {
        if(!Contains(obj))
        {
            base.Add(obj);
        }
    }
}

Поскольку List использует метод Equals исключительно для определения равенства, вы можете определить метод Equals на вашем типе T, чтобы убедиться, что вы получите желаемые результаты.