我在探索HashSet<T>
类型,但我不明白它在收藏中的地位。什么时候应该使用HashSet <T>类型?
有人可以用它来代替List<T>
吗?我认为HashSet<T>
的性能会更好,但我看不到其中的元素。
它仅用于枚举吗?
我在探索HashSet<T>
类型,但我不明白它在收藏中的地位。什么时候应该使用HashSet <T>类型?
有人可以用它来代替List<T>
吗?我认为HashSet<T>
的性能会更好,但我看不到其中的元素。
它仅用于枚举吗?
重要的关于HashSet<T>
是正确的,在名称:这是一个集。您可以使用单个套件做的唯一事情是确定其成员,并检查某个项目是否为成员。
,询问是否可以检索(例如set[45]
)被误解集的概念的单个元素。没有这样的事情,一组中的第45个元素。集合中的项目没有排序。集合{1,2,3}和{2,3,1}在每个方面都是相同的,因为它们具有相同的成员资格,并且成员资格是重要的。
这有点危险遍历一个HashSet<T>
,因为这样做强加在集中的项目订单。该命令并不是该集合的一个属性。你不应该依赖它。如果订购集合中的物品对您来说很重要,那么这个集合不是集合。
集合非常有限且拥有独特的成员。另一方面,它们非常快。
HashSet是由散列实现的集合。一个集合是不包含重复元素的值的集合。一组中的值通常也是无序的。所以不,一个集合不能用来替换一个列表(除非你应该首先使用一个集合)。
如果你想知道什么样的设置可能是有益的:显然,你想摆脱重复的地方。作为一个稍微有点人为的例子,假设您有一个软件项目的10.000版本的列表,并且您想知道有多少人为该项目做出了贡献。您可以使用Set<string>
并遍历修订列表并将每个修订的作者添加到该集。迭代完成后,集合的大小就是您正在寻找的答案。
但是Set不允许检索单个元素?像集合[45]? – 2009-08-07 23:35:56
为此,您需要遍历集合中的成员。其他典型的操作是检查该集合是否包含元素或获取集合的大小。 – earl 2009-08-07 23:39:40
性能将是一个坏的理由选择列表上的HashSet。相反,更好地捕捉你的意图?如果顺序很重要,那么Set(或HashSet)就不存在了。如果允许重复,也是如此。但是当我们不关心订单时,有很多情况,我们宁愿不要重复 - 那就是当你想要一个集合时。
'性能会是选择HashSet而不是List的坏理由:我只是不同意你。这就是说选择Dictionray而不是两个列表对性能没有帮助。看看[下面的文章](http://geekswithblogs.net/BlackRabbitCoder/archive/2011/02/03/c.net-little-wonders-the-useful-but-overlooked-sets.aspx) – 2011-02-26 06:17:26
@奥斯卡:我没有说组合不会更快 - 我说这将是选择它们的糟糕基础。如果你试图表示一个有序的集合,那么一个集合根本就不能工作,而试图对其进行索引是错误的;如果你想要的收藏品没有订单,那么一套完美 - 而且速度很快。但重要的是第一个问题:你想表达什么? – 2011-02-26 15:49:22
但想一想。如果你想继续检查给定的字符串是否是某个10,000个字符串集合的成员,在技术上,'string []。Contains'和'HashSet
HashSet<T>
是.NET框架中的一种数据结构,它能够将mathematical set表示为对象。在这种情况下,它使用散列码(每个项目的GetHashCode
结果)比较设置元素的相等性。
一个集合与列表的不同之处在于它只允许在其中包含一个相同元素。如果您尝试添加第二个相同的元素,则HashSet<T>
将仅返回false
。事实上,查找元素非常快(O(1)
时间),因为内部数据结构只是一个散列表。
如果您想知道使用哪个,请注意,使用List<T>
,其中HashSet<T>
是appropiate是不是最大的错误,虽然它可能会允许你在哪儿集合中的不良重复的项目问题。更重要的是,查找(项目检索)效率要高得多 - 理想的情况是O(1)
(用于理想的桶装)而不是O(n)
时间 - 这在很多情况下非常重要。
List<T>
用于存储有序的信息集。如果您知道列表元素的相对顺序,则可以在一段时间内访问它们。但是,要确定元素在列表中的位置或检查它是否存在于列表中,查找时间是线性的。另一方面,HashedSet<T>
不保证存储的数据的顺序,并因此为其元素提供恒定的访问时间。
顾名思义,HashedSet<T>
是实现set semantics的数据结构。数据结构被优化以实现集合操作(即联合,差异,相交),这对于传统的列表实现来说无法高效完成。
因此,选择使用哪种数据类型实际上取决于您试图对您的应用程序做什么。如果您不在乎您的元素是如何在一个系列中订购的,并且只想要检查是否存在,请使用HashSet<T>
。否则,请考虑使用List<T>
或其他合适的数据结构。
另一个警告:集通常只允许一个元素出现。 – 2009-08-07 23:39:33
哈希集合最常见的用法是查看它们是否包含某个元素,它接近于O(1)操作(假设一个足够强的散列函数),而不是检查列表包含是O(n)(以及它是O(log n)的排序集)。所以如果你做了很多检查,不管某个项目是否包含在某个列表中,hahssets可能会提高性能。如果你只是遍历它们,那么不会有太大的区别(遍历整个集合是O(n),与列表相同,并且在添加项目时,哈希集合有更多的开销)。
不,你不能索引集,这是没有意义的,无论如何,因为集是没有顺序的。如果你添加一些项目,设置会不记得哪一个是第一,和第二等
如果您只遍历它们,那么与List相比,HashSet方法会增加相当多的内存使用量。 – SamuelWarren 2010-05-26 18:23:10
总之 - 任何时候,你都倾向于使用词典(或词典其中S是T的属性),那么你应该考虑一个HashSet(或HashSet的+对T这相当于S上实现IEquatable)
除非你关心密钥,那么你应该使用字典。 – Hardwareguy 2010-10-19 20:56:30
这里的,我用一个HashSet<string>
一个真实的例子:我的语法高亮显示的虚幻的文件
部分是一项新功能,highlights Doxygen-style comments。我需要能够判断@
或\
命令是否有效,以确定是以灰色(有效)还是红色(无效)显示它。我有一个HashSet<string>
所有有效的命令,所以无论何时我在词法分析器中使用@xxx
标记,我都会使用validCommands.Contains(tokenText)
作为我的O(1)有效性检查。我真的不关心任何东西,除了在设置有效命令命令存在。让我们看看我面对的替代方案:
Dictionary<string, ?>
:我使用什么类型的值?这个价值是没有意义的,因为我只打算使用ContainsKey
。注意:在.NET 3.0之前,这是O(1)查找的唯一选择 - 为3.0添加了HashSet<T>
并为4.0扩展了ISet<T>
。List<string>
:如果我保持排序的名单,我可以使用BinarySearch
,这是O(log n)的(没看到这一点上面提到的)。但是,由于我的有效命令列表是永不变更的固定列表,因此这绝不会比简单的列表更适合...string[]
:再次,Array.BinarySearch
给出O(log n)性能。如果列表很短,这可能是表现最佳的选项。它总是比HashSet
,Dictionary
或List
更少的空间开销。即使是BinarySearch
,对于大型设备来说也不算快,但对于小型设备来说,这值得尝试。尽管我有几百件物品,所以我通过了这个。感谢一个真实世界的例子 – 2014-07-06 02:16:20
甲HashSet<T>
实现ICollection<T>
接口:
public interface ICollection<T> : IEnumerable<T>, IEnumerable
{
// Methods
void Add(T item);
void Clear();
bool Contains(T item);
void CopyTo(T[] array, int arrayIndex);
bool Remove(T item);
// Properties
int Count { get; }
bool IsReadOnly { get; }
}
甲List<T>
器具IList<T>
,它扩展了ICollection<T>
public interface IList<T> : ICollection<T>
{
// Methods
int IndexOf(T item);
void Insert(int index, T item);
void RemoveAt(int index);
// Properties
T this[int index] { get; set; }
}
一个HashSet已成立的语义,通过在内部散列表实现:
一个集合是不包含 重复元素,并且其元素 没有特定的顺序。
如果失去索引/位置/列表行为,HashSet获得了什么? (1)添加,O(1)通过索引检索,O(1)检索索引,O(1)通过索引检索,O(1)通过索引检索,O (n)查找/删除)。
HashSet的行为可以与使用Dictionary<TKey,TValue>
进行比较,只需将键值添加/删除并忽略字典值本身。您会希望字典中的键不会有重复的值,这就是“设置”部分的要点。
HashSet将用于删除IEnumerble集合中的重复元素。例如,
List<string> duplicatedEnumrableStrings = new List<string> {"abc", "ghjr", "abc", "abc", "yre", "obm", "ghir", "qwrt", "abc", "vyeu"};
HashSet<string> uniqueStrings = new HashSet(duplicatedEnumrableStrings);
那些码被运行后,uniqueStrings持有{ “ABC”, “ghjr”, “YRE”, “OBM”, “qwrt”, “vyeu”};
框架提供'SortedSet'数据结构的事实与您说的不是集合的属性相矛盾,或者指出开发团队的误解。 – Veverke 2016-08-03 16:07:36
我认为说'HashSet'中的项的顺序没有定义是更正确的,所以不要依赖迭代器的顺序。如果你迭代集合,因为你正在对集合中的项目进行一些操作,那么*除非*依赖与订单有关的任何东西,否则*不是危险的*。 'SortedSet'具有'HashSet' * plus *顺序的所有属性,但'SortedSet'不是从'HashSet'派生的;换句话说,* SortedSet是不同对象的有序集合*。 – Kit 2016-09-15 21:38:27
我很喜欢这个答案。但是,在呈现它时你显得很生气/沮丧/不高兴......这并不是我的忠实粉丝。 – pimbrouwers 2017-08-18 21:11:31