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





Попробуйте HashSet:
The HashSet(Of T) class provides high-performance set operations. A set is a collection that contains no duplicate elements, and whose elements are in no particular order...
The capacity of a HashSet(Of T) object is the number of elements that the object can hold. A HashSet(Of T) object's capacity automatically increases as elements are added to the object.
The HashSet(Of T) class is based on the model of mathematical sets and provides high-performance set operations similar to accessing the keys of the Dictionary(Of TKey, TValue) or Hashtable collections. In simple terms, the HashSet(Of T) class can be thought of as a Dictionary(Of TKey, TValue) collection without values.
A HashSet(Of T) collection is not sorted and cannot contain duplicate elements...
Если вы используете .NET 3.5, вы можете использовать HashSet<T>. Это правда, что .NET не обслуживает наборы так же хорошо, как Java.
Wintellect PowerCollections тоже может помочь.
кто-нибудь знает, почему это называется HashSet, а не просто Set?
Я подозреваю, что Set - это ключевое слово в некоторых языках, которое может вызвать проблемы.
set также является ключевым словом в C#
@Manish: Нет, это не так. См. Раздел 2.4.3 спецификации C# 3. Это имеет особое значение только для свойств.
@Jon Спасибо за просветление. Я всегда думал, что это ключевое слово. Скачал спецификацию C# 3.
Причина, по которой он называется HashSet, а не просто Set, та же, что и в Java - «Set» описывает интерфейс, тогда как «HashSet» описывает реализацию - в частности, это Set, поддерживаемый Hash Map. Таким образом, мы знаем (или должны строго ожидать), что вставка и доступ должны занимать время доступа O (1), в отличие от «LinkedListSet», что заставляет нас ожидать, что вставка и доступ займут время O (n).
что вы имеете в виду: «.NET не обслуживает наборы так же хорошо, как Java»? Этот набор чем-то несовершенный по сравнению с Java?
@ Луис: О каком наборе ты говоришь? В Java есть лоты различных реализаций Set для различных ситуаций. У .NET был один в .NET 3.5 (HashSet) и два в .NET 4 (HashSet и SortedSet). Тот факт, что нам пришлось дождаться появления .NET 3.5 для начала, довольно удивителен.
Пользуюсь Iesi.Collections http://www.codeproject.com/KB/recipes/sets.aspx
Он используется во многих проектах OSS, впервые я столкнулся с ним в NHibernate.
Взгляните на PowerCollections на CodePlex. Помимо Set и OrderedSet у него есть несколько других полезных типов коллекций, таких как Deque, MultiDictionary, Bag, OrderedBag, OrderedDictionary и OrderedMultiDictionary.
Для других коллекций есть также Библиотека общих коллекций C5.
Я использую оболочку вокруг Dictionary<T, object>, сохраняя в значениях нули. Это дает O (1) добавление, поиск и удаление ключей, и во всех смыслах и целях действует как набор.
Вы должны иметь в виду, что это примерно эквивалентно std :: unordered_set. std :: set заказан. Например, вы можете быстро найти начальную и конечную точку диапазона и выполнить итерацию от начала до конца, просматривая элементы в порядке нажатия клавиш. SortedDictionary является примерно эквивалентен std :: set.
Я знаю, что это старый поток, но я столкнулся с той же проблемой и обнаружил, что HashSet очень ненадежен, потому что при одном и том же начальном значении GetHashCode () возвращал разные коды. Итак, я подумал, почему бы просто не использовать список и не скрыть метод добавления, подобный этому
public class UniqueList<T> : List<T>
{
public new void Add(T obj)
{
if (!Contains(obj))
{
base.Add(obj);
}
}
}
Поскольку List использует метод Equals исключительно для определения равенства, вы можете определить метод Equals для своего типа T, чтобы получить желаемые результаты.
Причина, по которой вы не захотите использовать это, заключается в том, что List.Contains имеет сложность O(n), что означает, что ваш метод Add теперь также становится сложным O(n). Предполагая, что размер внутренней коллекции не нужно изменять, Add для List и HashMap должен иметь сложность O(1). TL; DR: это будет работать, но это хакерский и менее эффективный способ.
Конечно, если ваши объекты не возвращают подходящее значение для GetHashCode, вы не должны помещать их в контейнер на основе хешей. Лучше исправить GetHashCode, чем использовать менее эффективный контейнер.
Если вы используете .NET 4.0 или новее:
В случае, если вам нужна сортировка, используйте SortedSet<T>. В противном случае, если вы этого не сделаете, используйте HashSet<T>, поскольку это O(1) для операций поиска и управления. В то время как SortedSet<T> - это O(log n) для операций поиска и управления.
К сожалению, HashSets не были добавлены до недавнего времени. Если вы работаете в более старой версии фреймворка, вам придется придерживаться своего измененного Dictionary <> или Hashtable.