2008-10-08 42 views
397

Có ai biết nếu có tương đương tốt với bộ sưu tập Set của Java trong C# không? Tôi biết rằng bạn có thể bắt chước một bộ bằng cách sử dụng một số Dictionary hoặc HashTable bằng cách điền nhưng bỏ qua các giá trị, nhưng đó không phải là một cách rất thanh lịch.C# Đặt bộ sưu tập?

+0

Bạn có thể tìm thấy một số thông tin cơ bản về Hashset tại đây. http://dotnetk.com/c-hashset-csharp/ –

Trả lời

55

Hãy thử HashSet:

Các HashSet (Of T) lớp cung cấp thiết lập hoạt động hiệu suất cao. Tập hợp là bộ sưu tập không chứa các phần tử trùng lặp và các phần tử của chúng không có thứ tự cụ thể ...

Công suất của đối tượng HashSet (T) là số phần tử mà đối tượng có thể giữ. Dung lượng của đối tượng HashSet (Of T) tự động tăng khi các phần tử được thêm vào đối tượng.

Lớp HashSet (Of T) dựa trên mô hình toán học và cung cấp các hoạt động thiết lập hiệu suất cao tương tự như truy cập các khóa của bộ sưu tập Dictionary(Of TKey, TValue) hoặc Hashtable. Nói một cách đơn giản, lớp HashSet (Of T) có thể được coi là bộ sưu tập Dictionary(Of TKey, TValue) không có giá trị.

Một HashSet (Of T) thu được không được sắp xếp và không thể chứa các thành phần trùng lặp ...

+5

Thật không may, HashSets không được thêm cho đến gần đây. Nếu bạn đang làm việc trong một phiên bản cũ hơn của khung công tác, bạn sẽ phải gắn bó với Từ điển bị bung của bạn <> hoặc Hashtable. –

388

Nếu bạn đang sử dụng .NET 3.5, bạn có thể sử dụng HashSet<T>. Đúng là .NET không phục vụ cho các bộ cũng như Java.

Wintellect PowerCollections cũng có thể giúp ích.

+2

có ai biết tại sao nó được gọi là HashSet và không chỉ là Set? – Wouter

+16

Tôi nghi ngờ rằng Set là một từ khóa ở một số ngôn ngữ, có thể gây ra vấn đề. –

+5

'Set' là một từ khóa trong VB. –

11

Có một cái nhìn tại PowerCollections qua tại CodePlex. Ngoài Set và OrderedSet nó có một vài loại sưu tập hữu ích khác như Deque, MultiDictionary, Bag, OrderedBag, OrderedDictionary và OrderedMultiDictionary.

Để có thêm bộ sưu tập, cũng có C5 Generic Collection Library.

12

Tôi sử dụng một trình bao bọc xung quanh Dictionary<T, object>, lưu trữ giá trị rỗng trong các giá trị. Điều này cho phép O (1) thêm, tra cứu và loại bỏ các khóa, và cho tất cả các ý định và mục đích hoạt động như một tập hợp.

+2

Bạn phải có nghĩa là nó tương đương với tiêu chuẩn :: unordered_set. std :: set được đặt hàng. Ví dụ: bạn có thể nhanh chóng tìm điểm bắt đầu và điểm kết thúc của một phạm vi và lặp lại từ đầu đến cuối, truy cập các mục theo thứ tự khóa. SortedDictionary * là * tương đương với std :: set. – doug65536

-4

Tôi biết đây là một chủ đề cũ, nhưng tôi đã chạy vào cùng một vấn đề và tìm thấy HashSet là rất không đáng tin cậy vì cho cùng một hạt giống, GetHashCode() trả về các mã khác nhau. Vì vậy, tôi nghĩ, tại sao không chỉ cần sử dụng một danh sách và ẩn các add phương pháp như thế này

public class UniqueList<T> : List<T> 
{ 
    public new void Add(T obj) 
    { 
     if(!Contains(obj)) 
     { 
      base.Add(obj); 
     } 
    } 
} 

Vì Danh sách sử dụng phương pháp Equals chỉ để xác định sự bình đẳng, bạn có thể xác định phương pháp Equals vào loại T của bạn để chắc chắn rằng bạn có được kết quả mong muốn.

+10

Lý do bạn không muốn sử dụng điều này là do 'List.Contains' có độ phức tạp' O (n) 'có nghĩa là phương thức' Add' của bạn bây giờ cũng trở thành phức tạp 'O (n)'. Giả sử bộ sưu tập bên trong không cần phải thay đổi kích thước, 'Thêm' cho cả' Danh sách' và 'HashMap' phải là độ phức tạp' O (1) '. TLDR: Điều này sẽ hiệu quả, nhưng nó rất mạnh và kém hiệu quả. –

+5

Chắc chắn, nếu các đối tượng của bạn không trả về một giá trị thích hợp cho GetHashCode, bạn không nên đặt chúng vào một thùng chứa dựa trên băm. Nó sẽ là tốt hơn để sửa chữa GetHashCode hơn để sử dụng một container ít hiệu quả. – bmm6o

+0

băm ở đâu? – mehmet6parmak

97

Cấu trúc dữ liệu HashSet<T>:

cấu trúc dữ liệu HashSet<T> Khung Class Library đã được giới thiệu trong .NET Framework 3.5. Bạn có thể tìm thấy danh sách đầy đủ các thành viên tại số MSDN reference page for HashSet<T>.

HashSet<T> được nhiều hay ít theo mô hình sau một mathematical set, có nghĩa là:

  1. Nó có thể chứa không có giá trị trùng lặp.

  2. Các thành phần của nó không theo thứ tự cụ thể; do đó loại không triển khai giao diện IList<T>, nhưng loại cơ bản hơn ICollection<T>. Kết quả là, các phần tử bên trong một bộ băm không thể được truy cập ngẫu nhiên thông qua các chỉ mục; chúng chỉ có thể được lặp lại thông qua một điều tra viên.

  3. Một số chức năng nhất định như Union, Intersection, IsSubsetOf, IsSupersetOf khả dụng. Đây có thể có ích khi làm việc với nhiều bộ.

Một điểm khác biệt giữa HashSet<T>List<T> là gọi phương thức một hash bộ của Add(item) trả về một giá trị Boolean: true nếu mục này đã được thêm vào, và false khác (vì nó đã được tìm thấy trong các thiết lập).

Tại sao không List<T>?

HashSet<T> chỉ đơn giản là một bộ sưu tập các đối tượng độc đáo, bạn có thể tự hỏi tại sao nó phải là cấu trúc dữ liệu. Một bình thường List<T> có thể có hành vi tương tự bằng cách kiểm tra nếu một đối tượng được tìm thấy trong danh sách trước khi thêm nó.

Câu trả lời ngắn là tốc độ. Tìm kiếm thông qua List<T> bình thường rất chậm rất nhanh vì có thêm nhiều thành phần được thêm vào. A HashSet<T> yêu cầu thiết kế cấu trúc cho phép tốc độ tìm kiếm và chèn nhanh.

Benchmarks:

Hãy so sánh tốc độ thực hiện của một HashSet<T> vs một List<T>.

Mỗi thử nghiệm bao gồm thêm số nguyên từ 0 đến 9.999 cho mỗi bộ sưu tập. Tuy nhiên, mod 25 được áp dụng cho mỗi số nguyên. Mod 25 làm cho các loại mục tối đa 25. Kể từ khi 10.000 phần tử được thêm vào, điều này đã buộc 400 va chạm xảy ra, cho phép các cấu trúc dữ liệu có cơ hội sử dụng các thuật toán tìm kiếm của chúng. Thời gian được đo 3 lần sau 10.000 lần thử nghiệm và tính trung bình.

Đừng chú ý quá nhiều đến thời gian chạy thử nghiệm cụ thể vì chúng phụ thuộc vào phần cứng của tôi, nhưng hãy xem chúng so sánh với nhau như thế nào.

  Average time [ms] 
---------------------------- 
HashSet<T>    2,290 
List<T>    5,505 

Bây giờ, hãy tạo các đối tượng phần tử thay vì các kiểu nguyên thủy. Tôi đã viết một lớp học nhanh chóng Person với ba trường: Name, LastNameID.Vì tôi không bao gồm bất kỳ cách cụ thể nào để so sánh các đối tượng, tất cả các phần tử sẽ được thêm vào mà không có xung đột. Lần này các đối tượng 1.000 Person được thêm vào mỗi bộ sưu tập cho một lần dùng thử. Tổng thời gian của 3 bộ 1.000 thử nghiệm được tính trung bình.

  Average time [ms] 
---------------------------- 
HashSet<Person>   201 
List<Person>   3,000 

Như bạn có thể thấy, sự khác biệt về thời gian chạy trở nên thiên văn khi sử dụng các đối tượng, làm cho lợi thế HashSet<T> trở nên thuận lợi.

+10

Sẽ không có 9975 va chạm thay vì 400? – sparebytes

+1

Đó là cách chúng tôi viết câu trả lời toàn diện tuyệt vời !! –

11

Nếu bạn đang sử dụng .NET 4.0 hoặc cao hơn:

Trong trường hợp bạn cần phải sắp xếp sau đó sử dụng SortedSet<T>. Nếu không, nếu không, hãy sử dụng HashSet<T> vì đó là O(1) để tìm kiếm và thao tác các thao tác. Trong khi SortedSet<T>O(log n) để tìm kiếm và thao tác các thao tác.