题
有没有人知道在C#中是否有与Java的Set
集合相当的好处?我知道你可以通过填充但忽略值来使用Dictionary
或HashTable
来模仿集合,但这不是一种非常优雅的方式。
解决方案
尝试 HashSet :
HashSet(Of <!>#8194; T)类提供高性能的集合操作。集合是一个不包含重复元素的集合,其元素没有特定的顺序......
HashSet(Of <!>#8194; T)对象的容量是对象可以容纳的元素数。 HashSet(Of <!>#8194; T)对象的容量会随着元素添加到对象而自动增加。
HashSet(Of <!>#8194; T)类基于数学集模型,提供类似于访问 Dictionary(Of <!>#8194; TKey,<!>#8194; TValue)或 Hashtable 集合。简单来说,HashSet(Of <!>#8194; T)类可以被认为是字典(Of <!>#8194; TKey,<!>#8194; TValue)没有值的集合。
HashSet(Of <!>#8194; T)集合未排序且不能包含重复元素...
其他提示
如果您使用的是.NET 3.5,则可以使用 HashSet<T>
。确实,.NET不像Java那样适应集合。
Wintellect PowerCollections 也可能有所帮助。
HashSet<T>
数据结构:
Framework Framework Library的IList<T>
数据结构是在.NET Framework 3.5中引入的。可以在 ICollection<T>
<的MSDN参考页面找到其成员的完整列表。 / A>
Union
或多或少地建模/ a>,这意味着:
-
它可能不包含重复值。
-
其元素没有特别的顺序;因此该类型不实现
Intersection
界面,但更基本的IsSubsetOf
。因此,哈希集内的元素不能通过索引随机访问;它们只能通过枚举器进行迭代。 -
某些设定功能,例如
IsSupersetOf
,List<T>
,Add(item)
,true
可用。当使用多组时,这些可以派上用场。
醇>
false
和Person
之间的另一个区别是调用哈希集的Name
方法返回一个布尔值:LastName
如果项目已添加,ID
否则(因为它已在设定)。
为什么不<=>?
由于<=>只是一个唯一对象的集合,您可能想知道为什么它必须是一个数据结构。正常的<=>可以通过在添加之前检查列表中是否找到对象来具有相同的行为。
简短的回答是速度。随着更多元素的添加,正常<=>搜索变得非常慢。 <=>要求结构设计允许快速搜索和插入速度。
<强>基准:强>
让我们比较<=>与<=>的表现速度。
每个试验包括为每个集合添加0到9,999的整数。但是,mod 25适用于每个整数。 Mod 25生成最大类型的项目25.由于添加了10,000个元素,因此强制发生400次冲突,使数据结构有机会使用其搜索算法。在10,000次试验后测量3次并取平均值。
不要过多关注测试的具体运行时间,因为它们取决于我的硬件,但看看它们是如何相互比较的。
Average time [ms]
----------------------------
HashSet<T> 2,290
List<T> 5,505
现在让我们创建元素对象而不是基本类型。我写了一个包含三个字段的快速<=>类:<=>,<=>和<=>。由于我没有包含任何比较对象的特定方法,因此将添加所有元素而不会发生冲突。这次1000个<=>对象被添加到每个集合中进行单次试验。平均3组1000次试验的总次数。
Average time [ms]
----------------------------
HashSet<Person> 201
List<Person> 3,000
正如您所看到的,运行时间的差异在使用物体时变得天文数字,使<=>有利。
如果您使用的是.NET 4.0或更高版本:
如果您需要排序,请使用 SortedSet<T>
。否则,如果不这样做,则使用 HashSet<T>
,因为O(1)
用于搜索和操纵操作。而O(log n)
<=>用于搜索和操作操作。
我使用Iesi.Collections http://www.codeproject.com/KB/recipes /sets.aspx
它在许多OSS项目中使用,我首先在NHibernate中看到它
我在Dictionary<T, object>
周围使用包装器,在值中存储空值。这使得O(1)在键上添加,查找和删除,并且所有意图和目的都像集合一样。
在CodePlex上查看 PowerCollections 。除了Set和OrderedSet之外,它还有一些其他有用的集合类型,如Deque,MultiDictionary,Bag,OrderedBag,OrderedDictionary和OrderedMultiDictionary。
对于更多馆藏,还有 C5通用馆藏图书馆。
您可以在几个小时内实现自己的可行集实现。我必须这样做时使用了这个(抱歉,我没有方便的代码): http://java.sun.com/j2se/1.4.2/docs/api/java/util/Set.html
我知道这是一个旧线程,但我遇到了同样的问题,发现HashSet非常不可靠,因为给定相同的种子,GetHashCode()返回不同的代码。所以,我想,为什么不使用List并隐藏像这样的添加方法
public class UniqueList<T> : List<T>
{
public new void Add(T obj)
{
if(!Contains(obj))
{
base.Add(obj);
}
}
}
因为List仅使用Equals方法来确定相等性,所以可以在T类型上定义Equals方法以确保获得所需的结果。