.NET HashTable Vs Dictionary - Từ điển có thể nhanh như vậy không?


276

Tôi đang cố gắng tìm ra khi nào và tại sao nên sử dụng Từ điển hoặc HashTable. Tôi đã thực hiện một chút tìm kiếm ở đây và thấy mọi người nói về những lợi thế chung của Từ điển mà tôi hoàn toàn đồng ý, điều này dẫn đến lợi thế đấm bốc và mở hộp để đạt được hiệu suất nhẹ.

Nhưng tôi cũng đã đọc từ điển sẽ không luôn trả về các đối tượng theo thứ tự chúng được chèn, điều đó được sắp xếp. Trường hợp như một HashTable sẽ. Theo tôi hiểu, điều này dẫn đến HashTable nhanh hơn rất nhiều trong một số tình huống.

Câu hỏi của tôi là thực sự, những tình huống đó có thể là gì? Tôi chỉ sai trong các giả định của tôi ở trên? Những tình huống nào bạn có thể sử dụng để chọn một tình huống khác, (vâng, tình huống cuối cùng hơi mơ hồ).


5
Tôi sẽ không ủng hộ điều này, nhưng nghiệp lực của bạn là 7.777 và tôi không muốn trở thành người gây rắc rối cho bạn.
CaptainMarvel

Câu trả lời:


298

System.Collections.Generic.Dictionary<TKey, TValue>System.Collections.Hashtablecác lớp đều duy trì cấu trúc dữ liệu bảng băm bên trong. Không ai trong số họ đảm bảo duy trì trật tự của các mặt hàng.

Bỏ các vấn đề về quyền anh / unboxing sang một bên, hầu hết thời gian, chúng sẽ có hiệu suất rất giống nhau.

Sự khác biệt về cấu trúc chính giữa chúng là Dictionarydựa vào chuỗi (duy trì danh sách các mục cho mỗi nhóm bảng băm) để giải quyết va chạm trong khi Hashtablesử dụng tính năng xử lý lại để giải quyết va chạm (khi xảy ra va chạm, thử một hàm băm khác để ánh xạ khóa vào thùng) .

Có rất ít lợi ích khi sử dụng Hashtablelớp nếu bạn đang nhắm mục tiêu cho .NET Framework 2.0+. Nó thực sự bị lỗi thời bởi Dictionary<TKey, TValue>.


21
@ Jon- Việc xâu chuỗi và luyện tập lại được thảo luận sâu ở đây- msdn.microsoft.com/en-us/l Library
ms379571 (VS.80) .aspx

Cảm ơn cả hai người. Chỉ cần tìm thấy trang đó khi Richard đăng nó ... Sẽ hỏi về Chaining nhưng trang MSDN thực sự hữu ích!
Jon

6
@Mehrdad - Điều không rõ ràng với tôi về cách giải quyết va chạm là thế này: nếu nhiều khóa có thể dẫn đến cùng một hàm băm, thì làm thế nào để bạn đảm bảo bạn nhận được giá trị đúng khi tra cứu, tức là làm thế nào để hàm biết phần tử nào trở về? Trong msdn.microsoft.com/en-us/l Library / ms379571% 28VS.80% 29.aspx, nó nói, "Thay vì đẩy lùi trong trường hợp va chạm, như được thực hiện với lớp Hashtable, Từ điển chỉ đơn giản là xâu chuỗi mọi va chạm vào danh sách của xô. " Điều này có nghĩa là khi sử dụng Từ điển, các va chạm không phải là điều mà nhà phát triển phải lo lắng?
Howiecamp

6
@Howiecamp: Điều này không thực sự khác biệt nhiều Hashtable. Các bảng băm lưu trữ 3 mẩu thông tin trong một mục: khóa băm, chính khóa và giá trị. Đối với các mục có hàm băm bằng nhau, nó sẽ phải duyệt qua danh sách để tìm mục có khóa bằng nhau và trả về giá trị của nó. Điều này là khá đúng cho Hashtablequá. Là một nhà phát triển sử dụng Dictionarybình thường, bạn không cần phải lo lắng về điều đó.
Mehrdad Afshari

@Mehrdad Để rõ ràng, cả hai đối tượng Hashtable và Dictionary đều tự lưu trữ khóa và cả hai cũng ẩn các xung đột với nhà phát triển?
Howiecamp

111

Tôi đoán nó không có ý nghĩa gì với bạn bây giờ. Nhưng chỉ để tham khảo cho những người ghé qua

Kiểm tra hiệu suất - Sắp xếp danh sách so với Sắp xếp từ điển so với Từ điển so với Hashtable

Cấp phát bộ nhớ:

Kiểm tra hiệu năng sử dụng bộ nhớ

Thời gian sử dụng để chèn:

Thời gian sử dụng để chèn

Thời gian để tìm kiếm một mục:

Thời gian để tìm kiếm một mục


Rất thú vị khi danh sách được sắp xếp có tra cứu FASTER hơn hashtable. Tôi nghĩ rằng hashtable là O (1) so với danh sách được sắp xếp O (logn). Rõ ràng là hashtable hút. Tôi sẽ không bao giờ sử dụng nó.
John Henckel

@JohnHenckel không, danh sách được sắp xếp có tra cứu chậm hơn. Hệ số hiệu suất lớn hơn có nghĩa là hiệu suất tốt hơn và sử dụng bộ nhớ tốt hơn. Vì vậy, danh sách được sắp xếp có mức sử dụng bộ nhớ tốt nhất theo biểu đồ nhưng nó hút ở các khu vực khác như chèn và tra cứu.
C0DEF52

31

Sự khác biệt giữa Hashtable và Từ điển

Từ điển:

  • Từ điển trả về lỗi nếu chúng ta cố gắng tìm một khóa không tồn tại.
  • Từ điển nhanh hơn Hashtable vì không có quyền anh và unboxing.
  • Từ điển là một loại chung có nghĩa là chúng ta có thể sử dụng nó với bất kỳ loại dữ liệu.

Hashtable:

  • Hashtable trả về null nếu chúng ta cố gắng tìm một khóa không tồn tại.
  • Hashtable chậm hơn từ điển vì nó yêu cầu quyền anh và unboxing.
  • Hashtable không phải là một loại chung chung,

24

Một sự khác biệt quan trọng khác là loại Hashtable hỗ trợ nhiều người đọc không khóa và một người viết cùng một lúc, trong khi Từ điển thì không.


8
Từ điển đồng thời sẽ hỗ trợ (.Net 4.0)
Tamilmaran

1
Tôi không chắc nếu tôi hiểu câu trả lời này. Nhìn vào đây msdn.microsoft.com/en-us/l Library / Nói nó "Để hỗ trợ nhiều người viết, tất cả các thao tác trên Hashtable phải được thực hiện thông qua trình bao bọc được trả về bởi phương thức Đồng bộ hóa, với điều kiện là không có luồng nào đọc đối tượng Hashtable. " Điều đó dường như làm cho tính năng "nhiều người đọc không khóa" trở nên vô dụng, vì vậy chúng tôi quay lại việc phải khóa tất cả quyền truy cập vào Hashtable, giống như với Từ điển.
RenniePet

16

Bài viết MSDN: " Dictionary<TKey, TValue>Lớp này có cùng chức năng với Hashtablelớp. Một Dictionary<TKey, TValue> loại cụ thể (khác Object) có hiệu suất tốt hơn so Hashtablevới loại giá trị vì các yếu tố Hashtablethuộc loại Objectvà do đó, quyền anh và unboxing thường xảy ra nếu lưu trữ hoặc lấy một loại giá trị ".

Liên kết: http://msdn.microsoft.com/en-us/l Library / 4yh14awz (v = vs.90) .aspx


11

Cả hai đều có cùng một lớp (bạn có thể nhìn vào quá trình tháo gỡ). HashTable được tạo đầu tiên trước khi .Net có generic. Từ điển, tuy nhiên là một lớp chung và cung cấp cho bạn lợi ích gõ mạnh mẽ. Tôi sẽ không bao giờ sử dụng HashTable vì Từ điển chi phí cho bạn không có gì để sử dụng.


8

Một sự khác biệt quan trọng Hashtablelà chủ đề an toàn. Hashtableđã tích hợp sẵn nhiều luồng an toàn Hashtablecho trình đọc / trình ghi đơn (MR / SW), có nghĩa là cho phép MỘT trình ghi cùng với nhiều trình đọc mà không bị khóa. Trong trường hợp Dictionarykhông có an toàn luồng, nếu bạn cần an toàn luồng, bạn phải thực hiện đồng bộ hóa của riêng mình.

Để giải thích thêm:

Hashtable, cung cấp một số an toàn luồng thông qua thuộc tính Đã đồng bộ hóa, trả về trình bao bọc an toàn luồng xung quanh bộ sưu tập. Trình bao bọc hoạt động bằng cách khóa toàn bộ bộ sưu tập trên mỗi thao tác thêm hoặc xóa. Do đó, mỗi luồng đang cố truy cập vào bộ sưu tập phải chờ đến lượt để lấy một khóa. Điều này không thể mở rộng và có thể gây suy giảm hiệu suất đáng kể cho các bộ sưu tập lớn. Ngoài ra, thiết kế không hoàn toàn được bảo vệ khỏi các điều kiện chủng tộc.

Các lớp .NET Framework 2.0 bộ sưu tập thích List<T>, Dictionary<TKey, TValue>, vv không cung cấp bất kỳ đồng bộ hóa thread; mã người dùng phải cung cấp tất cả đồng bộ hóa khi các mục được thêm hoặc xóa trên nhiều luồng đồng thời Nếu bạn cần an toàn kiểu cũng như an toàn luồng, hãy sử dụng các lớp bộ sưu tập đồng thời trong .NET Framework. Đọc thêm ở đây.


3

Từ điển có lợi thế là một loại chung chung, làm cho loại này an toàn và nhanh hơn một chút do không cần quyền anh. Bảng so sánh sau (được xây dựng bằng các câu trả lời được tìm thấy trong một câu hỏi SO tương tự ) minh họa một số lý do khác hỗ trợ từ điển trên bảng băm (hoặc ngược lại).


1

Nếu bạn quan tâm đến việc đọc sẽ luôn trả về các đối tượng theo thứ tự chúng được chèn vào Từ điển, bạn có thể xem qua

OrderedDixi - các giá trị có thể được truy cập thông qua một chỉ số nguyên (theo thứ tự các mục được thêm vào) SortedDixi - các mục được tự động sắp xếp


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.