HashSet和 HashSet有什么区别?和列表

发布于 2024-11-16 12:01:00 字数 174 浏览 4 评论 0原文

您能解释一下 .NET 中的 HashSetList 之间有什么区别吗?

也许您可以举个例子来解释在什么情况下 HashSet 应该优先于 List

Can you explain what is the difference between HashSet<T> and List<T> in .NET?

Maybe you can explain with an example in what cases HashSet<T> should be preferred against List<T> ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

南城追梦 2024-11-23 12:01:00

与列表不同的是...

  1. HashSet 是一个没有重复成员的列表。

  2. 因为 HashSet 被限制为只包含唯一的条目,所以内部结构针对搜索进行了优化(与列表相比) - 它的速度要快得多

  3. 添加到 HashSet 返回一个布尔值 - 如果由于 Set 中已存在而导致添加失败,则返回 false

  4. 可以对集合执行数学集合运算:Union/Intersection/IsSubsetOf 等。

  5. HashSet 不实现 IList 仅 ICollection

  6. 您不能在 HashSet 中使用索引,只能使用枚举器。

使用 HashSet 的主要原因是您对执行 Set 操作感兴趣。

给定 2 个集合:hashSet1 和 hashSet2

 //returns a list of distinct items in both sets
 HashSet set3 = set1.Union( set2 );

与使用 LINQ 的等效操作相比要快得多。写起来也比较整齐!

Unlike a List<> ...

  1. A HashSet is a List with no duplicate members.

  2. Because a HashSet is constrained to contain only unique entries, the internal structure is optimised for searching (compared with a list) - it is considerably faster

  3. Adding to a HashSet returns a boolean - false if addition fails due to already existing in Set

  4. Can perform mathematical set operations against a Set: Union/Intersection/IsSubsetOf etc.

  5. HashSet doesn't implement IList only ICollection

  6. You cannot use indices with a HashSet, only enumerators.

The main reason to use a HashSet would be if you are interested in performing Set operations.

Given 2 sets: hashSet1 and hashSet2

 //returns a list of distinct items in both sets
 HashSet set3 = set1.Union( set2 );

flies in comparison with an equivalent operation using LINQ. It's also neater to write!

囍孤女 2024-11-23 12:01:00

更准确地说,让我们用示例来演示,

您不能像下面的示例一样使用 HashSet。

HashSet<string> hashSet1 = new HashSet<string>(){"1","2","3"};
for (int i = 0; i < hashSet1.Count; i++)
    Console.WriteLine(hashSet1[i]);

hashSet1[i] 会产生错误:

无法将 [] 索引应用于类型表达式
'System.Collections.Generic.HashSet'

您可以使用 foreach 语句:

foreach (var item in hashSet1)
    Console.WriteLine(item);

您不能将重复的项目添加到 HashSet,而 List 允许您这样做,并且
当你向HashSet添加一个项目时,你可以检查它是否包含该项目。

HashSet<string> hashSet1 = new HashSet<string>(){"1","2","3"};
if (hashSet1.Add("1"))
   Console.WriteLine("'1' is successfully added to hashSet1!");
else
   Console.WriteLine("'1' could not be added to hashSet1, because it contains '1'");

HashSet 有一些有用的函数,如 IntersectWith、UnionWith、IsProperSubsetOf、ExceptWith、SymmetricExceptWith等

IsProperSubsetOf

HashSet<string> hashSet1 = new HashSet<string>() { "1", "2", "3", "4" };
HashSet<string> hashSet2 = new HashSet<string>() { "2", "4", "6", "8" };
HashSet<string> hashSet3 = new HashSet<string>() { "1", "2", "3", "4", "5" };
if (hashSet1.IsProperSubsetOf(hashSet3))
    Console.WriteLine("hashSet3 contains all elements of hashSet1.");
if (!hashSet1.IsProperSubsetOf(hashSet2))
    Console.WriteLine("hashSet2 does not contains all elements of hashSet1.");

UnionWith

HashSet<string> hashSet1 = new HashSet<string>() { "3", "4" };
HashSet<string> hashSet2 = new HashSet<string>() { "2", "4", "6", "8" };
hashSet1.UnionWith(hashSet2); //hashSet1 -> 3, 2, 4, 6, 8

IntersectWith

HashSet<string> hashSet1 = new HashSet<string>() { "3", "4", "8" };
HashSet<string> hashSet2 = new HashSet<string>() { "2", "4", "6", "8" }
hashSet1.IntersectWith(hashSet2);//hashSet1 -> 4, 8

ExceptWith

 HashSet<string> hashSet1 = new HashSet<string>() { "1", "2", "3", "5", "6" };
 HashSet<string> hashSet2 = new HashSet<string>() { "1", "2", "3", "4" };
 hashSet1.ExceptWith(hashSet2);//hashSet1 -> 5, 6

SymmetricExceptWith

 HashSet<string> hashSet1 = new HashSet<string>() { "1", "2", "3", "5", "6" };
 HashSet<string> hashSet2 = new HashSet<string>() { "1", "2", "3", "4" };
 hashSet1.SymmetricExceptWith(hashSet2);//hashSet1 -> 4, 5, 6

顺便说一下,HashSet 中不保留顺序。在示例中,我们最后添加了元素“2”,但它是第二个顺序:

HashSet<string> hashSet1 = new HashSet<string>() { "3", "4", "8" };
hashSet1.Add("1");    // 3, 4, 8, 1
hashSet1.Remove("4"); // 3, 8, 1
hashSet1.Add("2");    // 3, 2 ,8, 1

To be more precise lets demonstrate with examples,

You can not use HashSet like in the following example.

HashSet<string> hashSet1 = new HashSet<string>(){"1","2","3"};
for (int i = 0; i < hashSet1.Count; i++)
    Console.WriteLine(hashSet1[i]);

hashSet1[i] would produce an error:

Cannot apply indexing with [] to an expression of type
'System.Collections.Generic.HashSet'

You can use foreach statement:

foreach (var item in hashSet1)
    Console.WriteLine(item);

You can not add duplicated items to HashSet while List allows you to do this and
while you are adding an item to HashSet, you can check wheter it contains the item or not.

HashSet<string> hashSet1 = new HashSet<string>(){"1","2","3"};
if (hashSet1.Add("1"))
   Console.WriteLine("'1' is successfully added to hashSet1!");
else
   Console.WriteLine("'1' could not be added to hashSet1, because it contains '1'");

HashSet has some useful functions like IntersectWith, UnionWith, IsProperSubsetOf, ExceptWith, SymmetricExceptWith etc.

IsProperSubsetOf:

HashSet<string> hashSet1 = new HashSet<string>() { "1", "2", "3", "4" };
HashSet<string> hashSet2 = new HashSet<string>() { "2", "4", "6", "8" };
HashSet<string> hashSet3 = new HashSet<string>() { "1", "2", "3", "4", "5" };
if (hashSet1.IsProperSubsetOf(hashSet3))
    Console.WriteLine("hashSet3 contains all elements of hashSet1.");
if (!hashSet1.IsProperSubsetOf(hashSet2))
    Console.WriteLine("hashSet2 does not contains all elements of hashSet1.");

UnionWith:

HashSet<string> hashSet1 = new HashSet<string>() { "3", "4" };
HashSet<string> hashSet2 = new HashSet<string>() { "2", "4", "6", "8" };
hashSet1.UnionWith(hashSet2); //hashSet1 -> 3, 2, 4, 6, 8

IntersectWith:

HashSet<string> hashSet1 = new HashSet<string>() { "3", "4", "8" };
HashSet<string> hashSet2 = new HashSet<string>() { "2", "4", "6", "8" }
hashSet1.IntersectWith(hashSet2);//hashSet1 -> 4, 8

ExceptWith :

 HashSet<string> hashSet1 = new HashSet<string>() { "1", "2", "3", "5", "6" };
 HashSet<string> hashSet2 = new HashSet<string>() { "1", "2", "3", "4" };
 hashSet1.ExceptWith(hashSet2);//hashSet1 -> 5, 6

SymmetricExceptWith :

 HashSet<string> hashSet1 = new HashSet<string>() { "1", "2", "3", "5", "6" };
 HashSet<string> hashSet2 = new HashSet<string>() { "1", "2", "3", "4" };
 hashSet1.SymmetricExceptWith(hashSet2);//hashSet1 -> 4, 5, 6

By the way, the order is not preserved in HashSets. In the example, we added element "2" last but it is in the second order:

HashSet<string> hashSet1 = new HashSet<string>() { "3", "4", "8" };
hashSet1.Add("1");    // 3, 4, 8, 1
hashSet1.Remove("4"); // 3, 8, 1
hashSet1.Add("2");    // 3, 2 ,8, 1
愿与i 2024-11-23 12:01:00

HashSet 是一个类,旨在为您提供 O(1) 包含查找(即,此集合是否包含特定对象,并快速告诉我答案) )。

List 是一个类,旨在为您提供一个具有 O(1) 随机访问且可以动态增长的集合(想想动态数组)。您可以在 O(n) 时间内测试包含性(除非列表已排序,否则您可以在 O(log n) 时间内进行二分搜索)。

也许您可以举个例子来解释在什么情况下 HashSet 应该优先于 List

当你想测试 O(1) 中的包含时

A HashSet<T> is a class designed to give you O(1) lookup for containment (i.e., does this collection contain a particular object, and tell me the answer fast).

A List<T> is a class designed to give you a collection with O(1) random access than can grow dynamically (think dynamic array). You can test containment in O(n) time (unless the list is sorted, then you can do a binary search in O(log n) time).

Maybe you can explain with an example in what cases HashSet<T> should be prefered against List<T>

When you want to test containment in O(1).

橘虞初梦 2024-11-23 12:01:00

当您想要执行以下操作时,请使用 List

  • 按特定顺序存储项目集合。

如果您知道所需项目的索引(而不是项目本身的值),则检索时间复杂度为 O(1)。如果您不知道索引,则查找该项目需要更多时间,对于未排序的集合,O(n)

当您想要执行以下操作时,请使用 Hashset

  • 快速查找某个对象是否包含在集合中。

如果您知道要查找的内容的名称,则查找时间为O(1)(即“哈希”部分)。它不像 List 那样维护顺序,并且您无法存储重复项(添加重复项没有效果,这是“Set”部分)。

何时使用 Hashset 的一个示例是,如果您想查明拼字游戏中玩的单词是否是英语(或其他语言)中的有效单词。如果您想构建一个可供此类游戏的在线版本的所有实例使用的 Web 服务,那就更好了。

List 将是创建记分板以跟踪玩家得分的良好数据结构。

Use a List<T> when you want to:

  • Store a collection of items in a certain order.

If you know the index of the item you want (rather than the value of the item itself) retrieval is O(1). If you don't know the index, finding the item takes more time, O(n) for an unsorted collection.

Use a Hashset<T> when you want to:

  • Quickly find out if a certain object is contained in a collection.

If you know the name of the thing you want to find, Lookup is O(1) (that's the 'Hash' part). It doesn't maintain an ordering like the List<T> does and you can't store duplicates (adding a duplicate has no effect, that's the 'Set' part).

An example of when to use a Hashset<T> would be if you want to find out if a word played in a game of Scrabble is a valid word in English (or other language). Even better would be if you wanted to build a web service to be used by all instances of an online version of such a game.

A List<T> would be a good data structure for creating the scoreboard to track player scores.

攒一口袋星星 2024-11-23 12:01:00

列表是一个有序列表。它

  • 通过整数索引来访问,
  • 可以包含重复项,
  • 具有可预测的顺序,

HashSet 是一个集合。它:

  • 可以阻止重复项目(请参阅 Add(T)
  • 不保证项目的顺序集合中的项目
  • 具有您期望对集合进行的操作,例如、IntersectWith、IsProperSubsetOf、UnionWith。

当您想要访问集合时,列表更合适,就好像它就像一个可以追加、插入和删除项目的数组一样。如果您想将您的集合视为一个项目“包”(其中顺序并不重要),或者您想使用 IntersectWith 或 UnionWith 等操作将其与其他集合进行比较,那么 HashSet 是更好的选择。

List is an ordered list. It is

  • accessed by an integer index
  • can contain duplicates
  • has a predictable order

HashSet is a set. It:

  • Can block duplicate items (see Add(T))
  • Does not guarantee the order of the items within the set
  • Has operations you would expect on a set, e.g., IntersectWith, IsProperSubsetOf, UnionWith.

List is more appropriate when you want to access you collection as though it were like an array to which you could append, insert and remove items. HashSet is a better choice if you want to treat your collection like a "bag" of items in which order is not important or when you want to compare it with other sets using the operations such as IntersectWith or UnionWith.

心病无药医 2024-11-23 12:01:00

列表不一定是唯一的,而哈希集则是唯一的。

List is not necessarily unique, while hashset is, for one.

书信已泛黄 2024-11-23 12:01:00

列表是 T 类型对象的有序集合,与数组不同,您可以添加和删除条目。

您将使用一个列表,您希望按照存储顺序引用成员,并且通过位置而不是项目本身来访问它们。

HashSet 就像一个字典,项本身既是键也是值,不保证顺序。

您可以使用 HashSet 来检查集合中是否有对象

A List is an ordered collection of objects of Type T that unlike an array you can add and remove entries.

You would use a list where you want to reference the members in the order you stored them and you are accessing them by an position rather than the item itself.

A HashSet is like a dictionary that the item itself is the key as well as the value, the ordering is not guaranteed.

You would use a HashSet where you want to check that an object is in the collection

没企图 2024-11-23 12:01:00

如果您决定将这些数据结构应用于数据驱动开发中的实际使用,则 HashSet 对于测试数据适配器源的复制、数据清理和迁移非常有帮助。

另外,如果使用 DataAnnotations 类,则可以在类属性上实现 Key 逻辑,并使用 HashSet 有效控制自然索引(聚集或非聚集),这在 List 实现中将非常困难。

使用列表的一个强大选择是在视图模型上实现多种媒体的泛型,例如将类列表发送到 DropDownList Helper 的 MVC 视图,以及通过 WebApi 作为 JSON 构造发送。该列表允许典型的类集合逻辑,并保持灵活性,以更像“接口”的方法来计算不同介质的单个视图模型。

If you decide to apply these data structures to actual usage in data-driven development, a HashSet is VERY helpful in testing replication against data adapter sources, for data cleansing and migration.

Also, if using the DataAnnotations Class, one can implement Key logic on class properties and effectively control a Natural Index (clustered or not) with a HashSet, where this would be very difficult in a List implementation.

A strong option for using a list is to implement generics for multiple mediums on a View Model, such as sending a list of classes to a MVC View for a DropDownList Helper, and also for sending as a JSON construct via WebApi. The list allows typical class collection logic, and keeps flexibility for a more "Interface" like approach to computing a single view model to different mediums.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文