我正在研究这种HashSet<T>
类型,但是我不知道它在收藏中的位置。
一个人可以用它代替List<T>
吗?我以为a的性能HashSet<T>
会更好,但是我看不到对其元素的单独访问。
它仅用于枚举吗?
我正在研究这种HashSet<T>
类型,但是我不知道它在收藏中的位置。
一个人可以用它代替List<T>
吗?我以为a的性能HashSet<T>
会更好,但是我看不到对其元素的单独访问。
它仅用于枚举吗?
Answers:
重要的事情HashSet<T>
就在名称中:它是set。单个集合唯一可以做的就是确定其成员,并检查某项是否为成员。
询问您是否可以检索单个元素(例如set[45]
)误解了集合的概念。集合中没有第45个元素。集合中的项目没有排序。集{1、2、3}和{2、3、1}在各个方面都是相同的,因为它们具有相同的成员资格,而成员资格就很重要。
对a进行迭代有些危险,HashSet<T>
因为这样做会对集合中的项目施加顺序。该顺序实际上不是集合的属性。您不应该依赖它。如果集合中项目的排序对您很重要,则该集合不是集合。
集确实是有限的,并且具有唯一的成员。另一方面,它们真的很快。
HashSet
未定义项目的顺序是更正确的,所以不要依赖迭代器的顺序。如果因为对集合中的项目进行了某些操作而对集合进行迭代,那么除非您依赖与订单相关的任何内容,否则这并不危险。A 具有加号顺序的所有属性,但是不衍生自; 换句话说,SortedSet是不同对象的有序集合。SortedSet
HashSet
SortedSet
HashSet
这是我使用的真实示例HashSet<string>
:
我的UnrealScript文件语法突出显示工具的一部分是一项新功能,可突出显示Doxygen样式的注释。我需要能够知道a @
或\
命令是否有效,以确定是将其显示为灰色(有效)还是红色(无效)。我拥有HashSet<string>
所有有效命令中的a,因此,每当我@xxx
在词法分析器中命中一个标记时,便将其validCommands.Contains(tokenText)
用作O(1)有效性检查。除了有效命令集中是否存在该命令外,我真的不在乎。让我们看看我面临的替代方案:
Dictionary<string, ?>
:我使用哪种类型的值?该值没有意义,因为我将要使用ContainsKey
。注意:在.NET 3.0之前,这是O(1)查找的唯一选择- HashSet<T>
为3.0添加并扩展ISet<T>
为4.0 实现。List<string>
:如果我对列表进行排序,则可以使用BinarySearch
,它是O(log n)(没有看到上面提到的这个事实)。但是,由于我的有效命令列表是一个不会更改的固定列表,因此,这比简单地...更合适。string[]
:同样,Array.BinarySearch
给出O(log n)性能。如果列表很短,那么这可能是性能最好的选择。它总是有空间开销小于HashSet
,Dictionary
或List
。即使使用BinarySearch
,对于大型集合来说也并不快,但是对于小型集合来说,值得尝试。我的有几百个物品,所以我将其传递给了我。一个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失去索引/位置/列表行为,它将获得什么收益?
从HashSet中添加和检索项目始终是由对象本身进行的,而不是通过索引器进行的,并且接近O(1)操作(列表为O(1)add,O(1)通过索引检索,O(n)查找) /去掉)。
Dictionary<TKey,TValue>
通过仅将键添加/删除键作为值,而忽略字典值本身,可以将HashSet的行为与使用a进行比较。您可能希望字典中的键没有重复的值,这就是“设置”部分的重点。
性能是选择HashSet而不是List的不好理由。相反,什么能更好地抓住您的意图?如果顺序很重要,则Set(或HashSet)不可用。如果允许重复,同样。但是在很多情况下,当我们不关心订单时,我们宁愿没有重复的商品,那就是您要购买Set的时候。
string[].Contains
并HashSet<string>.Contains
表达你的意图同样出色; 选择HashSet的原因是它将运行得更快。
HashSet是通过哈希实现的集合。集合是不包含重复元素的值的集合。集合中的值通常也无序。因此,不能,一个集合不能用于替换列表(除非您首先应该使用一个集合)。
如果您想知道一个集合可能有什么好处:显然,您想摆脱重复的任何地方。举一个人为设计的例子,假设您有一个软件项目的10,000个修订版本的列表,并且想知道有多少人对该项目做出了贡献。您可以使用Set<string>
和遍历修订列表,然后将每个修订的作者添加到集合中。一旦完成迭代,集合的大小就是您要寻找的答案。
HashSet将用于删除IEnumerable集合中的重复元素。例如,
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”};
散列集最常见的用途可能是查看散列集是否包含某个元素,该元素接近于散列集的O(1)操作(假设散列函数足够强大),而不是列表中包含是否为O( n)(以及排序为O(log n)的集合)。因此,如果您进行大量检查,以确定某个项目是否包含在某些列表中,那么HASSET可能会提高性能。如果只迭代它们,则不会有太大差异(整个集合的迭代次数为O(n),与列表和哈希集相同,添加项时开销更大)。
不,您无法索引集,因为集是无序的,所以无论如何这都没有意义。如果添加一些项目,则该集合将不会记住哪个是第一个,然后是第二个,依此类推。
HashSet<T>
是.NET框架中的数据结构,它能够将数学集表示为对象。在这种情况下,它使用哈希码(GetHashCode
每个项目的结果)比较集合元素的相等性。
集合与列表的不同之处在于,它仅允许一次出现包含在其中的相同元素。如果您尝试添加第二个相同的元素,它HashSet<T>
只会返回false
。确实,查找元素非常快(O(1)
时间),因为内部数据结构只是一个哈希表。
如果你想知道使用哪个,请注意,使用List<T>
其中HashSet<T>
的appropiate是不是最大的错误,虽然它可能会允许你在哪儿集合中的不良重复的项目问题。而且,查找(项目检索)的效率大大提高-理想情况下O(1)
(用于完美存储)而不是O(n)
时间-在许多情况下这非常重要。
List<T>
用于存储有序信息集。如果知道列表元素的相对顺序,则可以在恒定时间内访问它们。但是,要确定元素在列表中的位置或检查元素是否在列表中,查找时间是线性的。另一方面,HashedSet<T>
不保证所存储数据的顺序,因此为其元素提供恒定的访问时间。
顾名思义,它HashedSet<T>
是一种实现集合语义的数据结构。数据结构经过优化以实现集合操作(即,并集,差值,相交),而传统的List实现无法高效地完成此操作。
因此,选择使用哪种数据类型实际上取决于您要对应用程序执行的操作。如果您不关心元素在集合中的排序方式,只想枚举或检查是否存在,请使用HashSet<T>
。否则,请考虑使用List<T>
或其他合适的数据结构。
简而言之-任何时候您都想使用Dictionary(或Dictionary,其中S是T的属性),则应考虑使用HashSet(或HashSet +在T上实现IEquatable,它等于S)
在基本的预期方案中,HashSet<T>
当您要对两个集合进行比LINQ提供的更具体的设置操作时,应使用。LINQ方法,如Distinct
,Union
,Intersect
并Except
在大多数情况下是足够的,但有时你可能需要更细粒度的操作,并HashSet<T>
提供:
UnionWith
IntersectWith
ExceptWith
SymmetricExceptWith
Overlaps
IsSubsetOf
IsProperSubsetOf
IsSupersetOf
IsProperSubsetOf
SetEquals
LINQ和HashSet<T>
“重叠”方法之间的另一个区别是LINQ总是返回new IEnumerable<T>
,并且HashSet<T>
方法会修改源集合。
SortedSet
数据结构的事实要么与您所说的订单不是集合的属性相矛盾,要么指出开发团队的误解。