Câu hỏi Sự khác biệt giữa HashMap và Hashtable?


Sự khác biệt giữa một HashMap và một Hashtable trong Java?

Đó là hiệu quả hơn cho các ứng dụng không có luồng?


3122
2017-09-02 20:12


gốc


HashTable đã lỗi thời trong Java 1.7 và bạn nên sử dụng triển khai ConcurrentMap - MissFiona


Các câu trả lời:


Có một số khác biệt giữa HashMap và Hashtable trong Java:

  1. Hashtable Là đồng bộ, trong khi HashMap không phải là. Điều này làm cho HashMap tốt hơn cho các ứng dụng không có luồng, vì các đối tượng không đồng bộ thường hoạt động tốt hơn các đối tượng được đồng bộ hóa.

  2. Hashtable không cho phép null khóa hoặc giá trị. HashMap cho phép một null chìa khóa và số lượng bất kỳ null giá trị.

  3. Một trong các lớp con của HashMap là LinkedHashMap, vì vậy trong trường hợp bạn muốn thứ tự lặp lại có thể dự đoán (thứ tự chèn theo mặc định), bạn có thể dễ dàng hoán đổi HashMap cho một LinkedHashMap. Điều này sẽ không dễ dàng nếu bạn đang sử dụng Hashtable.

Vì việc đồng bộ hóa không phải là vấn đề cho bạn, tôi khuyên bạn nên HashMap. Nếu đồng bộ hóa trở thành một vấn đề, bạn cũng có thể xem xét ConcurrentHashMap.


3207
2017-09-02 23:02



Nếu bạn muốn tạo một chuỗi an toàn HashMap, hãy sử dụng Collections.synchronizedMap(). - Rok Strniša
Tôi cũng sẽ bình luận rằng cách tiếp cận ngây thơ đến an toàn luồng trong Hashtable ("đồng bộ hóa mọi phương pháp nên xử lý bất kỳ vấn đề tương tranh nào!") làm cho nó rất nhiều tệ hơn cho các ứng dụng luồng. Bạn nên đồng bộ hóa bên ngoài một cách tốt hơn HashMap (và suy nghĩ về hậu quả), hoặc sử dụng ConcurrentMap thực hiện (và khai thác API mở rộng của nó cho đồng thời). Tóm lại: lý do duy nhất để sử dụng Hashtable là khi một API cũ (từ năm 1996) yêu cầu nó. - erickson
HashMap cho phép lập trình linh hoạt để viết mã threadSafe khi chúng thực sự sử dụng nó. Nó hiếm khi xảy ra mà tôi cần một bộ sưu tập an toàn chủ đề như ConcurrentHashMap hoặc HashTable. Những gì tôi cần là tập hợp các chức năng nhất định hoặc một số câu lệnh nhất định trong một khối được đồng bộ hóa để trở thành chủ đề an toàn. - Gaurava Agarwal
Hashtable đã lỗi thời và chúng tôi đang sử dụng HashMap cho môi trường không an toàn. Nếu bạn cần sự an toàn của luồng thì bạn có thể sử dụng Collections.synchronizedMap () hoặc sử dụng ConcurrentHashMap để có hiệu quả hơn mà hashtable. - Maneesh Kumar
Nó đã lỗi thời nhưng không được dùng nữa và tôi tự hỏi tại sao lại như vậy. Tôi đoán loại bỏ lớp này (và Vector vì lý do tương tự) sẽ phá vỡ quá nhiều mã hiện có và chú thích với @Deprecated sẽ ngụ ý một ý định để loại bỏ mã, mà rõ ràng là không có. - Jilles van Gurp


Lưu ý rằng rất nhiều câu trả lời cho biết rằng Hashtable được đồng bộ hóa. Trong thực tế, điều này giúp bạn mua rất ít.  Việc đồng bộ hóa trên các phương thức accessor / mutator sẽ ngăn chặn hai luồng thêm hoặc loại bỏ khỏi bản đồ đồng thời, nhưng trong thế giới thực, bạn sẽ thường cần đồng bộ hóa bổ sung.

Một thành ngữ rất phổ biến là "kiểm tra rồi đặt" - tức là tìm một mục trong Bản đồ và thêm nó vào nếu nó chưa tồn tại. Đây không phải là cách thức hoạt động nguyên tử cho dù bạn sử dụng Hashtable hay HashMap.

Một HashMap được đồng bộ hóa tương đương có thể thu được bằng cách:

Collections.synchronizedMap(myMap);

Nhưng để thực hiện đúng logic này bạn cần đồng bộ hóa bổ sung của biểu mẫu:

synchronized(myMap) {
    if (!myMap.containsKey("tomato"))
        myMap.put("tomato", "red");
}

Ngay cả việc lặp qua các mục nhập của Hashtable (hoặc một HashMap thu được bởi Collections.synchronizedMap) không phải là luồng an toàn trừ khi bạn cũng bảo vệ Bản đồ khỏi bị sửa đổi thông qua đồng bộ hóa bổ sung.

Triển khai của ConcurrentMap giao diện (ví dụ ConcurrentHashMap) giải quyết một số điều này bằng cách bao gồm chủ đề ngữ nghĩa kiểm tra hành động an toàn nhu la:

ConcurrentMap.putIfAbsent(key, value);

583
2017-09-03 11:00



Cũng lưu ý rằng nếu một HashMap được sửa đổi, các trình vòng lặp trỏ đến nó được kết xuất không hợp lệ. - Chris K
Iterator sẽ ném ConcurrentModificationException, phải không? - Bhushan
Vì vậy, có bất kỳ sự khác biệt giữa đồng bộ (myMap) {...} và ConcurrentHashMap về chủ đề an toàn? - telebog
Rất đúng, tôi đã cố gắng giải thích tương tự ở đây ..lovehasija.com/2012/08/16/… - Love Hasija
@Bhushan: Nó sẽ ném trên một cơ sở nỗ lực tốt nhất, điều này là không đảm bảo hành vi: docs.oracle.com/javase/7/docs/api/java/util/HashMap.html - Matt Stephenson


Hashtable được coi là mã kế thừa. Không có gì về Hashtable mà không thể được thực hiện bằng cách sử dụng HashMap hoặc dẫn xuất của HashMap, vì vậy đối với mã mới, tôi không thấy bất kỳ lý do nào để quay lại Hashtable.


288
2018-06-25 01:46



Từ Hashtable javadoc (nhấn mạnh thêm): "Là nền tảng Java 2 v1.2, lớp này được trang bị thêm để triển khai giao diện Bản đồ, biến nó trở thành thành viên của khung công tác Java Collections"Tuy nhiên, bạn đúng rằng đó là mã kế thừa. Tất cả những lợi ích của việc đồng bộ hóa có thể thu được hiệu quả hơn với Collections.synchronizedMap (HashMap). (Tương tự như Vector là một phiên bản kế thừa của Collections.synchronizedList (ArrayList).) - Kip
@ aberrant80: tiếc là bạn không có sự lựa chọn giữa hai và phải sử dụng Hashtable khi lập trình cho J2ME ... - pwes
câu trả lời này sẽ bị xóa. nó chứa thông tin không chính xác và có rất nhiều upvotes. - anon58192932
@ anon58192932 Có thể chỉnh sửa câu hỏi để khắc phục sự cố không? - GC_
Chúng ta phải thu hút sự chú ý của người đăng @ aberrant80 hoặc quản trị viên bằng cách gắn cờ. Gắn cờ có thể giúp - sẽ thử ngay bây giờ. - anon58192932


Câu hỏi này thường được hỏi trong cuộc phỏng vấn để kiểm tra xem ứng viên có hiểu đúng cách sử dụng các lớp thu thập và biết các giải pháp thay thế có sẵn hay không.

  1. Lớp HashMap tương đương với Hashtable, ngoại trừ nó không được đồng bộ và cho phép null. (HashMap cho phép các giá trị null là khóa và giá trị trong khi Hashtable không cho phép null).
  2. HashMap không đảm bảo rằng thứ tự của bản đồ sẽ vẫn không đổi theo thời gian.
  3. HashMap không được đồng bộ hóa trong khi Hashtable được đồng bộ hóa.
  4. Iterator trong HashMap là không an toàn trong khi điều tra cho Hashtable không phải là và ném ConcurrentModificationException nếu bất kỳ Chủ đề nào khác sửa đổi bản đồ theo cấu trúc bằng cách thêm hoặc loại bỏ bất kỳ phần tử nào ngoại trừ phương thức remove () của Iterator. Nhưng đây không phải là một hành vi được đảm bảo và sẽ được thực hiện bởi JVM với nỗ lực tốt nhất.

Lưu ý về một số điều khoản quan trọng

  1. Đồng bộ hóa có nghĩa là chỉ một luồng có thể sửa đổi bảng băm tại một thời điểm. Về cơ bản, nó có nghĩa là bất kỳ chủ đề nào trước khi thực hiện cập nhật trên một hashtable sẽ phải có được một khóa trên đối tượng trong khi những người khác sẽ chờ đợi cho khóa được phát hành.
  2. Không an toàn là có liên quan từ bối cảnh của vòng lặp. Nếu một iterator đã được tạo trên một đối tượng collection và một số thread khác cố gắng sửa đổi đối tượng collection "structurally", một ngoại lệ sửa đổi đồng thời sẽ được ném. Có thể cho các chủ đề khác mặc dù gọi phương thức "set" vì nó không sửa đổi bộ sưu tập "structurally". Tuy nhiên, nếu trước khi gọi "set", bộ sưu tập đã được sửa đổi về cấu trúc, "IllegalArgumentException" sẽ bị ném.
  3. Sửa đổi cấu trúc có nghĩa là xóa hoặc chèn phần tử có thể thay đổi cấu trúc bản đồ một cách hiệu quả.

HashMap có thể được đồng bộ hóa bởi

Map m = Collections.synchronizeMap(hashMap);

Bản đồ cung cấp chế độ xem Bộ sưu tập thay vì hỗ trợ trực tiếp cho lặp lại  thông qua các đối tượng liệt kê. Chế độ xem bộ sưu tập tăng cường đáng kể  tính biểu cảm của giao diện, như được thảo luận sau trong phần này.  Bản đồ cho phép bạn lặp qua các khóa, giá trị hoặc cặp khóa-giá trị;  Hashtable không cung cấp tùy chọn thứ ba. Bản đồ cung cấp một cách an toàn  để xóa các mục nhập ở giữa quá trình lặp; Hashtable không.  Cuối cùng, Map sửa một thiếu sót nhỏ trong giao diện Hashtable.  Hashtable có một phương thức được gọi là contains, trả về true nếu  Hashtable chứa một giá trị đã cho. Với tên của nó, bạn sẽ mong đợi điều này  để trả về true nếu Hashtable chứa một khóa đã cho, bởi vì  khóa là cơ chế truy cập chính cho một Hashtable. Bản đô  giao diện loại bỏ nguồn gây nhầm lẫn này bằng cách đổi tên phương thức  containsValue. Ngoài ra, điều này cải thiện tính nhất quán của giao diện -  containsValue song song containsKey.

Giao diện bản đồ


148
2017-10-04 06:39



Câu trả lời này chứa ít nhất 2 điểm không chính xác thực tế đáng kể. Nó chắc chắn KHÔNG xứng đáng với nhiều upvotes này. - Stephen C
1) Trình lặp của HashMap KHÔNG an toàn. Chúng không nhanh. Có một sự khác biệt rất lớn về ý nghĩa giữa hai thuật ngữ đó. 2) Không có set hoạt động trên một HashMap. 3) put(...) hoạt động sẽ không ném IllegalArgumentException nếu có thay đổi trước đó. 4) Hành vi không nhanh của HashMap  cũng thế xảy ra nếu bạn thay đổi ánh xạ. 5) Hành vi không nhanh Là được bảo đảm. (Điều không được đảm bảo là hành vi của HashTable nếu bạn thực hiện sửa đổi đồng thời. Hành vi thực tế là ... không thể đoán trước.) - Stephen C
6) Hashtable không đảm bảo rằng thứ tự của các yếu tố bản đồ cũng sẽ ổn định theo thời gian. (Bạn có lẽ khó hiểu Hashtable với LinkedHashMap.) - Stephen C
Bất cứ ai khác thực sự lo lắng rằng sinh viên những ngày này đang nhận được ý tưởng sai lầm rằng nhận được "phiên bản đồng bộ" của các bộ sưu tập bằng cách nào đó có nghĩa là bạn không phải đồng bộ bên ngoài các hoạt động hợp chất? Ví dụ yêu thích của tôi về việc này thing.set(thing.get() + 1); mà thường xuyên hơn không bắt người mới bằng bất ngờ như hoàn toàn không được bảo vệ, đặc biệt là nếu get() và set() là các phương thức được đồng bộ hóa. Nhiều người trong số họ đang mong đợi phép thuật.
Các bộ lặp trên HashMap không an toàn - Abdul


HashMap: Việc triển khai Map giao diện sử dụng mã băm để lập chỉ mục một mảng. Hashtable: Xin chào, năm 1998 đã gọi. Họ muốn API bộ sưu tập của họ trở lại.

Nghiêm túc, mặc dù bạn nên tránh xa Hashtable hoàn toàn. Đối với các ứng dụng đơn luồng, bạn không cần thêm phí đồng bộ hóa. Đối với các ứng dụng đồng thời cao, đồng bộ hóa hoang tưởng có thể dẫn đến nạn đói, deadlocks hoặc các lần thu gom rác không cần thiết. Giống như Tim Howland đã chỉ ra, bạn có thể sử dụng ConcurrentHashMap thay thế.


107
2017-09-02 23:14



Điều này thực sự có ý nghĩa. ConcurrentHashMaps cho phép bạn tự do đồng bộ và gỡ lỗi dễ dàng hơn nhiều. - prap19


Hãy nhớ rằng HashTable là lớp kế thừa trước khi Java Collections Framework (JCF) được giới thiệu và sau đó được trang bị thêm để thực hiện Map giao diện. Vậy là Vector và Stack.

Do đó, luôn luôn tránh xa chúng trong mã mới vì luôn có sự thay thế tốt hơn trong JCF như những người khác đã chỉ ra.

Đây là Bộ sưu tập Java cheat sheet mà bạn sẽ thấy hữu ích. Lưu ý khối màu xám chứa lớp kế thừa HashTable, Vector và Stack.

enter image description here


104
2018-03-25 08:58





Ngoài những gì izb đã nói, HashMap cho phép các giá trị null, trong khi Hashtablekhông làm.

Cũng lưu ý rằng Hashtable kéo dài Dictionary lớp học, như là Javadocs trạng thái, đã lỗi thời và đã được thay thế bằng Map giao diện.


58
2017-09-02 20:30



nhưng điều đó không làm cho HashTable lỗi thời thực hiện nó? - Pacerier


Hãy xem biểu đồ này. Nó cung cấp so sánh giữa các cấu trúc dữ liệu khác nhau cùng với HashMap và Hashtable. So sánh là chính xác, rõ ràng và dễ hiểu.

Ma trận thu thập Java


50
2017-11-20 05:35



cảm ơn, bây giờ tôi biết những gì để lựa chọn trong kịch bản của tôi. - Well Smith


Hashtable tương tự như HashMap và có giao diện tương tự. Bạn nên sử dụng HashMap, trừ khi bạn yêu cầu hỗ trợ cho các ứng dụng cũ hoặc bạn cần đồng bộ hóa, như Hashtables các phương thức được đồng bộ hóa. Vì vậy, trong trường hợp của bạn vì bạn không phải là đa luồng, HashMaps là đặt cược tốt nhất của bạn.


39
2017-09-02 20:25





Một sự khác biệt quan trọng giữa hashtable và hashmap là Iterator trong HashMap là không nhanh trong khi điều tra cho Hashtable không phải là và ném ConcurrentModificationException nếu bất kỳ Chủ đề nào khác sửa đổi bản đồ theo cấu trúc bằng cách thêm hoặc loại bỏ bất kỳ phần tử nào ngoại trừ phương thức remove () của Iterator. Nhưng đây không phải là một hành vi được đảm bảo và sẽ được JVM thực hiện với nỗ lực tốt nhất. "

Nguồn của tôi: http://javarevisited.blogspot.com/2010/10/difference-between-hashmap-and.html


31
2017-09-08 06:40