C # Набір колекції?


488

Хтось знає, чи є гарний еквівалент Setколекції Java в C #? Я знаю, що ви можете дещо імітувати набір, використовуючи a Dictionaryабо a HashTableшляхом заселення, але ігноруючи значення, але це не дуже елегантний спосіб.

Відповіді:


142

Спробуйте HashSet :

Клас HashSet (Of T) забезпечує високопродуктивні операції з набору. Набір - це колекція, яка не містить дублікатів, а елементи яких не є в певному порядку ...

Ємність об'єкта HashSet (Of T) - це кількість елементів, які об'єкт може вмістити. Потужність об'єкта HashSet (Of T) автоматично збільшується, коли елементи додаються до об'єкта.

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

Колекція HashSet (Of T) не сортується і не може містити повторюваних елементів ...


8
На жаль, HashSets не додавались зовсім недавно. Якщо ви працюєте в більш старій версії фреймворку, вам доведеться дотримуватися розробленого словника <> або Hashtable.
Грег Д

413

Якщо ви використовуєте .NET 3.5, ви можете використовувати HashSet<T>. Це правда, що .NET не обслуговує набори так само, як і Java.

У PowerCollections Wintellect може допомогти теж.


16
Я підозрюю, що Set - це ключове слово на деяких мовах, яке може спричинити проблеми.
Джон Скіт

3
@Manish: Ні, це не так. Див. Розділ 2.4.3 специфікації C # 3. Він має лише особливе значення для властивостей.
Джон Скіт

28
Причина називати його HashSet, а не просто Set, така сама, як у Java - "Set" описує інтерфейс, тоді як "HashSet" описує реалізацію, зокрема це набір, підкріплений Hash Map. Таким чином, ми знаємо (або слід сильно очікувати), що вставка та доступ потребують часу O (1) доступу, порівняно з "LinkedListSet", що призведе до того, що ми очікуємо на вставку та доступ, щоб зайняти O (n) час.
Девід Сутер

5
що ти маєш на увазі ".NET не обслуговує набори так само, як і Java." Цей набір якось недосконалий у порівнянні з Java?
Луї Різ

34
@Louis: Про який набір ти говориш? У Java є безліч різних реалізацій Set для різних ситуацій. .NET мав один у .NET 3.5 (HashSet) і два в .NET 4 (HashSet і SortedSet). Той факт, що нам довелося чекати, поки почати .NET 3.5, - дуже дивно.
Джон Скіт

26

Якщо ви використовуєте .NET 4.0 або новішої версії:

У випадку, коли вам потрібно сортування, тоді використовуйте SortedSet<T>. Інакше, якщо ви цього не зробите, тоді використовуйте, HashSet<T>оскільки це O(1)для пошуку та маніпулювання операціями. Тоді SortedSet<T>як O(log n)для пошуку та маніпулювання операціями.



13

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


2
Ви повинні мати на увазі, що це приблизно еквівалентно std :: unordered_set. std :: set впорядковано. Наприклад, ви можете швидко знайти початкову і кінцеву точку діапазону і повторити від початку до кінця, відвідавши елементи впорядкованому ключі. SortedDictionary це приблизно еквівалентний станд :: набору.
doug65536


-5

Я знаю, що це стара тема, але я зіткнувся з тією ж проблемою і виявив, що HashSet є дуже ненадійним, оскільки, даючи одне і те ж насіння, GetHashCode () повертав різні коди. Отже, я подумав, чому б просто не використати Список та приховати такий метод додавання

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

Оскільки Список використовує метод рівних виключно для визначення рівності, ви можете визначити метод рівняння для типу Т, щоб переконатися, що ви отримаєте бажані результати.


13
Причина, яку ви не хочете використовувати це, полягає в тому, що List.Containsце O(n)складність, що означає, що ваш Addметод тепер стає також O(n)складним. Якщо припустити , що внутрішній збір не повинен бути змінений, Addдля обох Listі HashMapповинні бути O(1)складності. TLDR: Це буде працювати, але це хакі і менш ефективно.
Річард Марскелл - Дракір

6
Звичайно, якщо ваші об'єкти не повертають відповідного значення для GetHashCode, вам не слід ставити їх у контейнер на основі хешу. Було б краще виправити GetHashCode, ніж використовувати менш ефективний контейнер.
bmm6o
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.