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


3750

Sự khác biệt giữa a HashMapvà a Hashtabletrong Java là gì?

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


17
HashTable đã lỗi thời trong Java 1.7 và nên sử dụng triển khai Bản đồ đồng thời
MissFiona

@MissFiona Không, ConcurrentMapkhông cần thiết ở đây, như câu hỏi nói “các ứng dụng phi-ren” có nghĩa là luồng / đồng thời không phải là một vấn đề.
Basil Bourque

Câu trả lời:


3775

Có một số khác biệt giữa HashMapHashtabletrong Java:

  1. Hashtableđược đồng bộ hóa , trong khi đó HashMapthì không. Điều này làm HashMaptố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 so với các ứng dụng được đồng bộ hóa.

  2. Hashtablekhông cho phép nullkhóa hoặc giá trị. HashMapcho phép mộtnull khóa và bất kỳ số lượng nullgiá 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 có thể dự đoán được (theo thứ tự chèn theo mặc định), bạn có thể dễ dàng trao đổi HashMapcho a LinkedHashMap. Điều này sẽ không dễ dàng nếu bạn đang sử dụng Hashtable.

Vì đồng bộ hóa không phải là vấn đề đối với 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.


84
Nếu bạn muốn tạo một chủ đề HashMap an toàn, hãy sử dụng Collections.synchronizedMap().
Rok Strniša

275
Tôi cũng sẽ nhận xét rằng cách tiếp cận ngây thơ đối với an toàn luồng trong Hashtable("đồng bộ hóa mọi phương thức sẽ quan tâm đến bất kỳ vấn đề tương tranh nào!") Làm cho nó trở nên tồi tệ hơn nhiều đối với các ứng dụng luồng. Tốt hơn hết là bạn nên đồng bộ hóa bên ngoài HashMap(và suy nghĩ về hậu quả) hoặc sử dụng ConcurrentMaptriển khai (và khai thác API mở rộng của nó để đồng thời). Điểm mấu chốt: lý do duy nhất để sử dụng Hashtablelà khi API kế thừa (từ khoảng năm 1996) yêu cầu nó.
erickson

8
HashMap cung cấp sự linh hoạt cho lập trình viên để viết mã threadSafe khi họ thực sự sử dụng nó. Nó hiếm khi xảy ra rằng tôi cần một bộ sưu tập an toàn chủ đề như ConcảnHashMap hoặc HashTable. Những gì tôi cần là một số hàm nhất định hoặc các câu lệnh nhất định trong một khối được đồng bộ hóa để được an toàn.
Gaurava Agarwal

2
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 luồng. Nếu bạn cần sự an toàn của luồng thì bạn có thể sử dụng Collections.syn syncizedMap () hoặc sử dụng ConcảnHashMap hiệu quả hơn mà hashtable.
Maneesh Kumar

1
Nó đã lỗi thời nhưng không được tán thành và tôi tự hỏi tại sao lại như vậy. Tôi đoán việc loại bỏ lớp này (và Vector vì những lý do tương tự) sẽ phá vỡ quá nhiều mã hiện có và chú thích với @Deprecated sẽ ám chỉ ý định xóa mã, dường như không có.
Jilles van Gurp

682

Lưu ý rằng rất nhiều câu trả lời cho biết Hashtable được đồng bộ hóa. Trong thực tế điều này mua cho bạn rất ít. Đồng bộ hóa trên các phương thức accessor / mutator sẽ đồng thời dừng hai luồng thêm hoặc xóa khỏi bản đồ, 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 sau đó đặt" - tức là tìm kiếm một mục trong Mapvà thêm nó nếu nó chưa tồn tại. Đây không phải là một hoạt động nguyên tử cho dù bạn sử dụng HashtablehayHashMap .

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

Collections.synchronizedMap(myMap);

Nhưng để thực hiện chính xác logic này, bạn cần đồng bộ hóa thêm biểu mẫu:

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

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

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

ConcurrentMap.putIfAbsent(key, value);

53
Cũng lưu ý rằng nếu HashMap được sửa đổi, các trình vòng lặp trỏ đến nó sẽ được hiển thị không hợp lệ.
Chris K

3
Vì vậy, có sự khác biệt nào giữa đồng bộ hóa (myMap) {...} và ConcảnHashMap về mặt an toàn của luồng không?
telebog

3
Rất đúng, tôi đã cố gắng giải thích tương tự ở đây .. lovehasija.com/2012/08/16/ Khăn
Yêu Hasija

@Bhushan: Nó sẽ dựa trên cơ sở nỗ lực cao nhất, đây không phải là hành vi được đảm bảo: docs.oracle.com/javase/7/docs/api/java/util/HashMap.html
Matt Stephenson

Đã ở giữa một nhóm phát triển JVM trong nhiều năm, tôi có thể nói rằng đồng bộ hóa nội bộ của Hashtable ít nhất hữu ích cho việc chỉ tay đúng vào mã của khách hàng khi anh ta viết mã đồng thời tinh ranh. Chúng tôi đã nhận được một số khiếu nại về lỗi trong HashMap (và do đó "rõ ràng là" lỗi JDK / JVM), khi nguyên nhân là sửa đổi đồng thời.
Hot Licks

363

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


101
Từ Hashtable javadoc (nhấn mạnh thêm): "Kể từ 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ó thành thành viên của Khung công tác thu thập Java ." Tuy nhiên, bạn đúng rằng đó là mã kế thừa. Tất cả các lợi ích của việc đồng bộ hóa có thể thu được hiệu quả hơn với Collections.syn syncizedMap (HashMap). (Tương tự như Vector là phiên bản kế thừa của Collections.syn syncizedList (ArrayList).)
Kip

15
@ aberrant80: thật không may, bạn không có lựa chọn nào giữa hai người và phải sử dụng Hashtable khi lập trình cho J2ME ...
pwes

6
Câu trả lời này nên được xóa. nó chứa thông tin không chính xác và có rất nhiều upvote.
anon58192932

@ anon58192932 Có thể chỉnh sửa câu hỏi để sửa không?
GC_

1
Chúng tôi 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

189

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 hay không và nhận thức được các giải pháp thay thế có sẵn.

  1. Các HashMaplớp tương đương với Hashtable, ngoại trừ việc nó được không giấy phép null đồng bộ và. ( HashMapcho phép giá trị null là khóa và giá trị trong khi Hashtablekhông cho phép nulls).
  2. HashMap không đảm bảo rằng thứ tự của bản đồ sẽ không đổi theo thời gian.
  3. HashMaplà không đồng bộ trong khi Hashtableđược đồng bộ hóa.
  4. Trình lặp trong HashMapkhông an toàn trong khi trình liệt kê cho Hashtablekhông và ném ConcurrentModificationExceptionnếu có 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 xóa bất kỳ phần tử nào ngoại trừ phương thức Iteratorriêng của nó remove(). Nhưng đây không phải là một hành vi được bảo đảm và sẽ được JVM thực hiện với nỗ lực cao 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ộtHashtable sẽ phải có khóa trên đối tượng trong khi các khác sẽ chờ khóa được phát hành.
  2. Fail-safe có liên quan trong bối cảnh của các trình vòng lặp. Nếu một trình vòng lặp đã được tạo trên một đối tượng bộ sưu tập và một số luồng khác cố gắng sửa đổi đối tượng bộ sưu tập "về mặt cấu trúc", một ngoại lệ sửa đổi đồng thời sẽ được đưa ra. Có thể cho các luồng khác mặc dù gọi setphương thức vì nó không sửa đổi bộ sưu tập "theo cấu trúc". 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, IllegalArgumentExceptionsẽ 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 hiệu quả cấu trúc của bản đồ.

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 việc lặp lại thông qua các đối tượng liệt kê. Các khung nhìn của bộ sưu tập giú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 lại các khóa, giá trị hoặc cặp khóa-giá trị; Hashtablekhông cung cấp tùy chọn thứ ba. Bản đồ cung cấp một cách an toàn để loại bỏ các mục ở giữa vòng lặp; Hashtableđã không. Cuối cùng, Map sửa một thiếu sót nhỏ trong Hashtablegiao diện. Hashtablecó một phương thức gọi là chứa, trả về true nếu Hashtablechứa một giá trị đã cho. Đặt tên của nó, bạn mong muốn phương thức này trả về true nếu Hashtablechứa một khóa đã cho, bởi vì khóa là cơ chế truy cập chính cho a Hashtable. Giao diện Bả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 - containsValuesong song containsKey.

Giao diện bản đồ


19
Câu trả lời này chứa ít nhất 2 điểm không chính xác thực tế. Nó chắc chắn KHÔNG xứng đáng với nhiều upvote này.
Stephen C

58
1) Trình lặp của HashMap KHÔNG an toàn. Họ thất bại nhanh chóng. 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ó sethoạt động trên a HashMap. 3) put(...)Hoạt động sẽ không ném IllegalArgumentExceptionnếu có thay đổi trước đó. 4) Hành vi không nhanh HashMap cũng xảy ra nếu bạn thay đổi ánh xạ. 5) Hành vi không nhanh được đảm bảo. (Điều không được đảm bảo là hành vi của a HashTablenế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

25
6) Hashtablekhông đảm bảo rằng thứ tự của các yếu tố bản đồ sẽ ổn định theo thời gian. (Có lẽ bạn đang nhầm lẫn Hashtablevới LinkedHashMap.)
Stephen C

4
Bất cứ ai khác thực sự lo lắng rằng các sinh viên ngày nay đang có ý tưởng sai lầm rằng nhận được "phiên bản đồng bộ hóa" 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ộ hóa bên ngoài các hoạt động hỗn hợp? Ví dụ yêu thích của tôi về điều này thing.set(thing.get() + 1);thường xuyên hơn là không gây bất ngờ cho người mới vì hoàn toàn không được bảo vệ, đặc biệt là nếu get()set()là 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 trình vòng lặp trên HashMap không phải là không an toàn
Abdul

130

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

Nghiêm túc mà nói, tốt hơn hết là bạn nên tránh xa Hashtablehoàn toàn. Đối với các ứng dụng đơn luồng, bạn không cần thêm chi 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 chết đói, bế tắc hoặc tạm dừng thu gom rác không cần thiết. Giống như Tim Howland đã chỉ ra, bạn có thể sử dụng ConcurrentHashMapthay thế.


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

1
Đây có phải là cụ thể cho Java hoặc tất cả các thực hiện bản đồ băm.

125

Hãy nhớ rằng đó HashTablelà lớp kế thừa trước khi Khung sưu tập Java (JCF) được giới thiệu và sau đó được trang bị thêm để thực hiện Mapgiao diện. Đã Vectorvà đang Stack.

Do đó, 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.

Dưới đây là bảng cheat bộ sưu tập Java 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.

nhập mô tả hình ảnh ở đây


72

Có rất nhiều câu trả lời tốt đã được đăng. Tôi đang thêm một vài điểm mới và tóm tắt nó.

HashMapHashtablecả hai đều được sử dụng để lưu trữ dữ liệu ở dạng khóa và giá trị . Cả hai đều sử dụng kỹ thuật băm để lưu trữ các khóa độc đáo. Nhưng có nhiều sự khác biệt giữa các lớp HashMap và Hashtable được đưa ra dưới đây.

Bản đồ băm

  1. HashMaplà không đồng bộ. Nó không phải là luồng an toàn và không thể được chia sẻ giữa nhiều luồng mà không có mã đồng bộ hóa phù hợp.
  2. HashMap cho phép một khóa null và nhiều giá trị null.
  3. HashMap là một lớp mới được giới thiệu trong JDK 1.2.
  4. HashMap là nhanh
  5. Chúng tôi có thể làm cho HashMapđồng bộ hóa bằng cách gọi mã này
    Map m = Collections.synchronizedMap(HashMap);
  6. HashMap được duyệt qua Iterator.
  7. Lặp đi lặp lại HashMaplà thất bại nhanh chóng.
  8. HashMap kế thừa lớp AbstractMap.

Hashtable

  1. Hashtableđược đồng bộ hóa. Nó là chủ đề an toàn và có thể được chia sẻ với nhiều chủ đề.
  2. Hashtable không cho phép bất kỳ khóa hoặc giá trị null.
  3. Hashtable là một lớp kế thừa.
  4. Hashtable chậm
  5. Hashtable được đồng bộ hóa nội bộ và không thể không đồng bộ hóa.
  6. Hashtable được duyệt qua Enumerator và Iterator.
  7. ĐTVN Hashtablekhông phải là thất bại nhanh chóng.
  8. Hashtable kế thừa lớp Từ điển.

Đọc thêm Sự khác biệt giữa HashMap và Hashtable trong Java là gì?

nhập mô tả hình ảnh ở đây


Khá nhiều điều được đề cập trong câu trả lời này (dupicate of) - stackoverflow.com/a/39785829/432903 .
nguyện

Tại sao bạn nói ~ " Hashtable là một lớp kế thừa "? Tài liệu hỗ trợ cho việc đó ở đâu
IgorGanapolsky

2
@IgorGanapolsky bạn có thể đọc cái này - stackoverflow.com/questions/21086307/
Kiếm

Duy trì HashMap tốn kém hơn TreeMap. Bởi vì HashMap tạo ra các thùng bổ sung không cần thiết.
Abdul

64

Ngoài những gì izb đã nói, HashMapcho phép các giá trị null, trong khi đó Hashtablethì không.

Cũng lưu ý rằng việc Hashtablemở rộng Dictionarylớp, như trạng thái Javadocs , đã lỗi thời và đã được thay thế bởi Mapgiao diện.


3
nhưng điều đó không làm cho HashTable trở nên lỗi thời phải không?
Pacerier

@Pacerier HashTable đã lỗi thời kể từ Java 1.7.
Majid Ali Khan

62

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

Ma trận thu thập Java


49

Hashtabletương tự như HashMapvà 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, vì các Hashtablesphươ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 đa luồng, HashMapshãy đặt cược tốt nhất.


36

Một điểm khác biệt quan trọng khác giữa hashtable và hashmap là Iterator trong HashMap không hoạt động nhanh trong khi trình liệt kê cho Hashtable thì không và ném ConcurrencyModificationException nếu bất kỳ Thread nào khác sửa đổi cấu trúc bản đồ bằng cách thêm hoặc xóa 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 bảo đảm và sẽ được JVM thực hiện với nỗ lực cao nhất. "

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


36

Bên cạnh tất cả các khía cạnh quan trọng khác đã được đề cập ở đây, Bộ sưu tập API (ví dụ: giao diện Bản đồ) đang được sửa đổi mọi lúc để tuân thủ các bổ sung "mới nhất và lớn nhất" cho thông số Java.

Ví dụ, so sánh lặp lại Bản đồ Java 5:

for (Elem elem : map.keys()) {
  elem.doSth();
}

so với phương pháp Hashtable cũ:

for (Enumeration en = htable.keys(); en.hasMoreElements(); ) {
  Elem elem = (Elem) en.nextElement();
  elem.doSth();
}

Trong Java 1.8, chúng tôi cũng được hứa hẹn có thể xây dựng và truy cập HashMaps như trong các ngôn ngữ kịch bản cũ tốt:

Map<String,Integer> map = { "orange" : 12, "apples" : 15 };
map["apples"];

Cập nhật: Không, họ sẽ không hạ cánh trong 1.8 ... :(

Các cải tiến bộ sưu tập của Project Coin sẽ có trong JDK8?


34

Hashtableđược đồng bộ hóa, trong khi HashMapkhông. Điều đó làm cho Hashtablechậm hơn Hashmap.

Đối với các ứng dụng không có luồng, hãy sử dụng HashMapvì chúng khác nhau về chức năng.


30
  • HashTable được đồng bộ hóa, nếu bạn đang sử dụng nó trong một luồng duy nhất, bạn có thể sử dụng HashMap , đây là phiên bản không đồng bộ. Các đối tượng không đồng bộ thường có hiệu suất cao hơn một chút. Nhân tiện, nếu nhiều luồng truy cập đồng thời một HashMap và ít nhất một trong các luồng sửa đổi bản đồ theo cấu trúc, nó phải được đồng bộ hóa bên ngoài. Bạn có thể bọc bản đồ không đồng bộ trong một bản đồ được đồng bộ hóa bằng cách sử dụng:

    Map m = Collections.synchronizedMap(new HashMap(...));
  • HashTable chỉ có thể chứa đối tượng không null dưới dạng khóa hoặc dưới dạng giá trị. HashMap có thể chứa một khóa null và giá trị null.

  • Các trình lặp được trả về bởi Map là không nhanh, nếu bản đồ được sửa đổi cấu trúc bất cứ lúc nào sau khi trình lặp được tạo, theo bất kỳ cách nào ngoại trừ thông qua phương thức xóa riêng của trình lặp, trình lặp sẽ ném a ConcurrentModificationException. Do đó, khi đối mặt với sửa đổi đồng thời, iterator thất bại nhanh chóng và sạch sẽ, thay vì mạo hiểm hành vi độc đoán, không xác định tại một thời điểm không xác định trong tương lai. Trong khi đó, việc liệt kê được trả về bởi các phương thức khóa và phần tử của Hashtable không bị lỗi nhanh.

  • HashTable và HashMap là thành viên của Khung sưu tập Java (kể từ nền tảng Java 2 v1.2, HashTable đã được trang bị thêm để triển khai giao diện Bản đồ).

  • HashTable được coi là mã kế thừa, tài liệu khuyên nên sử dụng ConcảnHashMap thay cho Hashtable nếu muốn triển khai đồng thời an toàn cao cho luồng.

  • HashMap không đảm bảo thứ tự các phần tử được trả về. Đối với HashTable tôi đoán nó giống nhau nhưng tôi không hoàn toàn chắc chắn, tôi không tìm thấy nguồn tài nguyên rõ ràng.


30

HashMapHashtablecó sự khác biệt đáng kể về thuật toán là tốt. Không ai đã đề cập đến điều này trước đây vì vậy đó là lý do tại sao tôi đưa nó lên. HashMapsẽ xây dựng một bảng băm có sức mạnh hai kích thước, tăng nó một cách linh hoạt để bạn có tối đa khoảng tám phần tử (va chạm) trong bất kỳ nhóm nào và sẽ khuấy động các phần tử rất tốt cho các loại phần tử chung. Tuy nhiên, việc Hashtabletriển khai cung cấp kiểm soát tốt hơn và tốt hơn đối với băm nếu bạn biết bạn đang làm gì, cụ thể là bạn có thể sửa kích thước bảng bằng cách sử dụng số nguyên tố gần nhất với kích thước miền giá trị của bạn và điều này sẽ mang lại hiệu suất tốt hơn HashMap, tức là ít va chạm hơn đối với một số trường hợp.

Khác với sự khác biệt rõ ràng được thảo luận rộng rãi trong câu hỏi này, tôi thấy Hashtable là một chiếc xe "lái bằng tay" nơi bạn có quyền kiểm soát tốt hơn đối với băm và HashMap là đối tác "ổ tự động" thường sẽ hoạt động tốt.


27

Dựa trên thông tin ở đây , tôi khuyên bạn nên đi với HashMap. Tôi nghĩ rằng lợi thế lớn nhất là Java sẽ ngăn bạn sửa đổi nó trong khi bạn đang lặp lại nó, trừ khi bạn làm điều đó thông qua trình vòng lặp.


5
Nó không thực sự ngăn chặn nó, nó chỉ phát hiện ra nó và đưa ra một lỗi.
Bart van Heukelom

1
Tôi khá chắc chắn rằng nó sẽ ném ConncienModificationException trước khi bộ sưu tập cơ bản được sửa đổi, mặc dù tôi có thể sai.
pkaeding

Nó sẽ cố gắng phát hiện sửa đổi đồng thời và đưa ra một ngoại lệ. Nhưng nếu bạn đang làm bất cứ điều gì với chủ đề, nó không thể thực hiện bất kỳ lời hứa nào. Hoàn toàn bất cứ điều gì có thể xảy ra, bao gồm cả vỡ .
cHao

24

Một Collection- đôi khi được gọi là một thùng chứa - chỉ đơn giản là một đối tượng nhóm nhiều phần tử thành một đơn vị. Collections được sử dụng để lưu trữ, truy xuất, thao tác và giao tiếp dữ liệu tổng hợp. Khung bộ sưu tập W là một kiến ​​trúc hợp nhất để biểu diễn và thao tác các bộ sưu tập.

Các HashMap JDK1.2 và Hashtable JDK1.0, cả hai đều được sử dụng để đại diện cho một nhóm các đối tượng được biểu diễn theo <Key, Value>cặp. Mỗi <Key, Value>cặp được gọi là Entryđối tượng. Bộ sưu tập Entries được tham chiếu bởi đối tượng HashMapHashtable. Chìa khóa trong một bộ sưu tập phải là duy nhất hoặc đặc biệt. [vì chúng được sử dụng để truy xuất giá trị được ánh xạ một khóa cụ thể. các giá trị trong bộ sưu tập có thể được nhân đôi.]


« Thành viên khung siêu lớp, di sản và bộ sưu tập

Hashtable là một lớp kế thừa được giới thiệu JDK1.0, là một lớp con của lớp Từ điển. Từ JDK1.2Hashtable được thiết kế lại để thực hiện giao diện Bản đồ để tạo thành viên của khung bộ sưu tập. HashMap là một thành viên của Java Collection Framework ngay từ khi bắt đầu giới thiệu JDK1.2. HashMap là lớp con của lớp AbstractMap.

public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, Serializable { ... }

public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable { ... }

« Công suất ban đầu và hệ số tải

Dung lượng là số lượng xô trong bảng băm và công suất ban đầu chỉ đơn giản là công suất tại thời điểm bảng băm được tạo. Lưu ý rằng bảng băm đang mở: trong trường hợp " hashcollision", một nhóm duy nhất lưu trữ nhiều mục nhập, phải được tìm kiếm tuần tự. Hệ số tải là thước đo mức độ đầy đủ của bảng băm được phép nhận trước khi công suất của nó được tự động tăng lên.

HashMap xây dựng một bảng băm trống với dung lượng ban đầu mặc định (16) và hệ số tải mặc định (0,75). Khi Hashtable xây dựng hashtable trống với công suất ban đầu mặc định (11) và tỷ lệ tải / tỷ lệ lấp đầy (0,75).

Bản đồ băm & Hashtable

« Sửa đổi cấu trúc trong trường hợp va chạm băm

HashMap, Và nhiều nhấtHashtable trong trường hợp va chạm băm, họ lưu trữ các mục bản đồ trong danh sách được liên kết. Từ Java8HashMap nếu thùng băm phát triển vượt quá một ngưỡng nhất định, nhóm đó sẽ chuyển từ linked list of entries to a balanced tree. cải thiện hiệu suất trong trường hợp xấu nhất từ ​​O (n) đến O (log n). Trong khi chuyển đổi danh sách thành cây nhị phân, mã băm được sử dụng như một biến phân nhánh. Nếu có hai mã băm khác nhau trong cùng một nhóm, một mã được coi là lớn hơn và đi về bên phải của cây và một mã khác ở bên trái. Nhưng khi cả hai mã băm đều bằng nhau, HashMapgiả sử rằng các khóa có thể so sánh được và so sánh khóa để xác định hướng để có thể duy trì một số thứ tự. Đó là một thực hành tốt để làm cho các phím HashMap so sánh . Khi thêm mục nếu kích thước thùng đạtTREEIFY_THRESHOLD = 8chuyển đổi danh sách các mục được liên kết thành một cây cân bằng, khi loại bỏ các mục nhỏ hơnTREEIFY_THRESHOLDUNTREEIFY_THRESHOLD = 6 sẽ chuyển đổi cây cân bằng thành danh sách các mục được liên kết. Java 8 SRC , ngăn xếp

« Lặp lại chế độ xem bộ sưu tập, Không nhanh và Không an toàn

    +--------------------+-----------+-------------+
    |                    | Iterator  | Enumeration |
    +--------------------+-----------+-------------+
    | Hashtable          | fail-fast |    safe     |
    +--------------------+-----------+-------------+
    | HashMap            | fail-fast | fail-fast   |
    +--------------------+-----------+-------------+
    | ConcurrentHashMap  |   safe    |   safe      |
    +--------------------+-----------+-------------+

Iteratorlà một thất bại nhanh chóng trong tự nhiên. tức là nó ném ra ConcurrencyModificationException nếu một bộ sưu tập được sửa đổi trong khi lặp lại ngoài phương thức remove () của chính nó. Như Enumerationlà không an toàn trong tự nhiên. Nó không đưa ra bất kỳ ngoại lệ nào nếu một bộ sưu tập được sửa đổi trong khi lặp.

Theo Tài liệu API Java, Iterator luôn được ưu tiên hơn Bảng liệt kê.

LƯU Ý: Chức năng của giao diện liệt kê được nhân đôi bởi giao diện Iterator. Ngoài ra, Iterator thêm một thao tác loại bỏ tùy chọn và có tên phương thức ngắn hơn. Việc triển khai mới nên xem xét sử dụng Iterator theo sở thích để liệt kê.

Trong Java 5 đã giới thiệu Giao diện đồng thời : ConcurrentHashMap- một ConcurrentMaptriển khai hiệu năng cao đồng thời, được hỗ trợ bởi bảng băm. Việc triển khai này không bao giờ chặn khi thực hiện truy xuất và cho phép khách hàng chọn mức đồng thời để cập nhật. Nó được dự định như là một sự thay thế thả vào cho Hashtable: ngoài việc thực hiện ConcurrentMap, nó còn hỗ trợ tất cả các phương thức "di sản" đặc biệt Hashtable.

  • Mỗi HashMapEntrygiá trị đều biến động do đó đảm bảo tính nhất quán của hạt mịn đối với các sửa đổi dự kiến ​​và các lần đọc tiếp theo; mỗi lần đọc phản ánh bản cập nhật hoàn thành gần đây nhất

  • Các trình lặp và liệt kê là không an toàn - phản ánh trạng thái tại một số điểm kể từ khi tạo ra trình lặp / liệt kê; điều này cho phép đọc và sửa đổi đồng thời với chi phí giảm tính nhất quán. Họ không ném ConcExModificationException. Tuy nhiên, các trình vòng lặp được thiết kế để chỉ được sử dụng bởi một luồng tại một thời điểm.

  • Thích Hashtablenhưng không giống HashMap, lớp này không cho phép null được sử dụng làm khóa hoặc giá trị.

public static void main(String[] args) {

    //HashMap<String, Integer> hash = new HashMap<String, Integer>();
    Hashtable<String, Integer> hash = new Hashtable<String, Integer>();
    //ConcurrentHashMap<String, Integer> hash = new ConcurrentHashMap<>();

    new Thread() {
        @Override public void run() {
            try {
                for (int i = 10; i < 20; i++) {
                    sleepThread(1);
                    System.out.println("T1 :- Key"+i);
                    hash.put("Key"+i, i);
                }
                System.out.println( System.identityHashCode( hash ) );
            } catch ( Exception e ) {
                e.printStackTrace();
            }
        }
    }.start();
    new Thread() {
        @Override public void run() {
            try {
                sleepThread(5);
                // ConcurrentHashMap  traverse using Iterator, Enumeration is Fail-Safe.

                // Hashtable traverse using Enumeration is Fail-Safe, Iterator is Fail-Fast.
                for (Enumeration<String> e = hash.keys(); e.hasMoreElements(); ) {
                    sleepThread(1);
                    System.out.println("T2 : "+ e.nextElement());
                }

                // HashMap traverse using Iterator, Enumeration is Fail-Fast.
                /*
                for (Iterator< Entry<String, Integer> > it = hash.entrySet().iterator(); it.hasNext(); ) {
                    sleepThread(1);
                    System.out.println("T2 : "+ it.next());
                    // ConcurrentModificationException at java.util.Hashtable$Enumerator.next
                }
                */

                /*
                Set< Entry<String, Integer> > entrySet = hash.entrySet();
                Iterator< Entry<String, Integer> > it = entrySet.iterator();
                Enumeration<Entry<String, Integer>> entryEnumeration = Collections.enumeration( entrySet );
                while( entryEnumeration.hasMoreElements() ) {
                    sleepThread(1);
                    Entry<String, Integer> nextElement = entryEnumeration.nextElement();
                    System.out.println("T2 : "+ nextElement.getKey() +" : "+ nextElement.getValue() );
                    //java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextNode
                    //                                          at java.util.HashMap$EntryIterator.next
                    //                                          at java.util.Collections$3.nextElement
                }
                */
            } catch ( Exception e ) {
                e.printStackTrace();
            }
        }
    }.start();

    Map<String, String> unmodifiableMap = Collections.unmodifiableMap( map );
    try {
        unmodifiableMap.put("key4", "unmodifiableMap");
    } catch (java.lang.UnsupportedOperationException e) {
        System.err.println("UnsupportedOperationException : "+ e.getMessage() );
    }
}
static void sleepThread( int sec ) {
    try {
        Thread.sleep( 1000 * sec );
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

« Null Keys và Null Values

HashMapcho phép tối đa một khóa null và bất kỳ số lượng giá trị null nào. Trong trường hợp Hashtablekhông cho phép ngay cả một khóa null và giá trị null, nếu khóa hoặc giá trị null thì nó sẽ ném NullPulumException. Thí dụ

«Đã đồng bộ hóa, chủ đề an toàn

Hashtableđược đồng bộ nội bộ. Do đó, nó rất an toàn để sử dụng Hashtabletrong các ứng dụng đa luồng. Trường hợp như HashMapkhông được đồng bộ nội bộ. Do đó, không an toàn khi sử dụng HashMaptrong các ứng dụng đa luồng mà không đồng bộ hóa bên ngoài. Bạn có thể đồng bộ hóa bên ngoài HashMapbằng Collections.synchronizedMap()phương pháp.

« Hiệu suất

Như Hashtableđược đồng bộ hóa nội bộ, điều này làm cho Hashtablehơi chậm hơn so với HashMap.


@Xem


18

Đối với các ứng dụng theo luồng, bạn có thể thường xuyên sử dụng ConcảnHashMap- tùy thuộc vào yêu cầu về hiệu suất của bạn.


17

1. HashmapHashTablecả khóa lưu trữ và giá trị.

2. Hashmapcó thể lưu trữ một khóa như null. Hashtablekhông thể lưu trữ null.

3. HashMapkhông được đồng bộ nhưng Hashtableđược đồng bộ hóa.

4. HashMapcó thể được đồng bộ hóa vớiCollection.SyncronizedMap(map)

Map hashmap = new HashMap();

Map map = Collections.SyncronizedMap(hashmap);

16

Ngoài sự khác biệt đã đề cập, cần lưu ý rằng kể từ Java 8, HashMaptự động thay thế các nút (linked list) sử dụng trong mỗi thùng với TreeNodes (cây đỏ-đen), do đó ngay cả khi va chạm băm cao tồn tại, trường hợp xấu nhất khi tìm kiếm

O (log (n)) cho HashMap Vs O (n) trong Hashtable.

* Những cải tiến nói trên vẫn chưa được áp dụng cho Hashtable, nhưng chỉ đến HashMap, LinkedHashMapConcurrentHashMap.

FYI, hiện tại,

  • TREEIFY_THRESHOLD = 8 : nếu một nhóm chứa nhiều hơn 8 nút, danh sách được liên kết được chuyển thành cây cân bằng.
  • UNTREEIFY_THRESHOLD = 6 : khi một thùng trở nên quá nhỏ (do loại bỏ hoặc thay đổi kích thước), cây được chuyển đổi trở lại danh sách được liên kết.

14

Có 5 điểm khác biệt cơ bản với HashTable và HashMaps.

  1. Bản đồ cho phép bạn lặp lại và truy xuất các khóa, giá trị và cả các cặp khóa-giá trị, trong đó HashTable không có tất cả khả năng này.
  2. Trong Hashtable có một hàm chứa (), rất khó sử dụng. Bởi vì ý nghĩa của chứa là hơi sai lệch. Cho dù nó có nghĩa là chứa khóa hoặc chứa giá trị? khó hiểu Điều tương tự trong Bản đồ chúng ta có các hàm ContainsKey () và ContainsValue (), rất dễ hiểu.
  3. Trong hashmap, bạn có thể loại bỏ phần tử trong khi lặp, an toàn. nơi mà nó là không thể trong hashtables.
  4. HashTables theo mặc định được đồng bộ hóa, vì vậy nó có thể được sử dụng với nhiều luồng dễ dàng. Khi HashMaps không được đồng bộ hóa theo mặc định, do đó chỉ có thể được sử dụng với một luồng duy nhất. Nhưng bạn vẫn có thể chuyển đổi HashMap thành đồng bộ hóa bằng cách sử dụng chức năng Đồng bộ hóa (Map m) của lớp Bộ sưu tập.
  5. HashTable sẽ không cho phép khóa null hoặc giá trị null. Như HashMap cho phép một khóa null và nhiều giá trị null.

13

Đóng góp nhỏ của tôi:

  1. Khác biệt đầu tiên và quan trọng nhất giữa HashtableHashMapđó là, HashMapkhông an toàn cho luồng trong khi Hashtablelà một bộ sưu tập an toàn theo luồng.

  2. Sự khác biệt quan trọng thứ hai giữa HashtableHashMaplà hiệu suất, vì HashMapkhông được đồng bộ hóa nên nó hoạt động tốt hơn Hashtable.

  3. Sự khác biệt thứ ba về Hashtablevs HashMapHashtablelớp lỗi thời và bạn nên sử dụng ConcurrentHashMapthay thế Hashtabletrong Java.


11

HashMap: Đây là một lớp có sẵn trong gói java.util và nó được sử dụng để lưu trữ phần tử ở định dạng khóa và giá trị.

Hashtable: Đây là một lớp kế thừa đang được công nhận trong khung bộ sưu tập.


Nếu nó là như vậy, nó nên được bình luận không phải là câu trả lời.
gautam gautam

10

HashTable là một lớp kế thừa trong jdk không nên được sử dụng nữa. Thay thế tập quán của nó bằng ConcảnHashMap . Nếu bạn không yêu cầu an toàn luồng, hãy sử dụng HashMap không phải là luồng an toàn nhưng nhanh hơn và sử dụng ít bộ nhớ hơn.


Bởi vì tôi nghĩ rằng các câu trả lời khác vào thời điểm đó đã không loại bỏ HashTable nhưng giải thích rằng đó là chủ đề an toàn. Sự thật là ngay khi bạn nhìn thấy HashTable trong mã, bạn nên thay thế nó bằng ConcảnHashMap mà không bỏ qua một nhịp. Và nếu an toàn luồng không phải là vấn đề đáng lo ngại thì HashMap có thể được sử dụng để cải thiện hiệu suất một chút.
jontejj

10
  1. Hashtable được đồng bộ hóa trong khi HashMap không.
  2. Một điểm khác biệt nữa là iterator trong phần mềm HashMapkhông an toàn trong khi trình liệt kê choHashtable không. Nếu bạn thay đổi bản đồ trong khi lặp, bạn sẽ biết.
  3. HashMapcho phép giá trị null trong đó, trong khi Hashtablekhông.

3
Trình lặp HashMap là fail-fast không phải fail-safe. Đó là lý do tại sao chúng ta có ConcảnHashMap cho phép sửa đổi trong khi lặp. Kiểm tra bài đăng này journaldev.com/122/ Lời
Pankaj

9

HashMap và HashTable

  • Một số điểm quan trọng về HashMap và HashTable. xin vui lòng đọc chi tiết dưới đây.

1) Hashtable và Hashmap thực hiện giao diện java.util.Map 2) Cả Hashmap và Hashtable đều là bộ sưu tập dựa trên hàm băm. và làm việc trên băm. vì vậy đây là những điểm tương đồng của HashMap và HashTable.

  • Sự khác biệt giữa HashMap và HashTable là gì?

1) Sự khác biệt đầu tiên là HashMap không phải là luồng an toàn Trong khi HashTable là ThreadSafe
2) HashMap có hiệu suất tốt hơn vì nó không phải là luồng an toàn. trong khi hiệu suất Hashtable khôn ngoan không tốt hơn vì nó là luồng an toàn. vì vậy nhiều luồng không thể truy cập Hashtable cùng một lúc.


2
Bỏ phiếu vì câu trả lời này không đúng ở một số khía cạnh. Hashtable không triển khai giao diện Bản đồ mà chỉ mở rộng lớp Từ điển, đã lỗi thời.
Yannis Sermetziadis

8

Hashtable:

Hashtable là cấu trúc dữ liệu giữ lại các giá trị của cặp khóa-giá trị. Nó không cho phép null cho cả khóa và giá trị. Bạn sẽ nhận được NullPointerExceptionnếu bạn thêm giá trị null. Nó được đồng bộ hóa. Vì vậy, nó đi kèm với chi phí của nó. Chỉ một luồng có thể truy cập HashTable tại một thời điểm cụ thể.

Ví dụ :

import java.util.Map;
import java.util.Hashtable;

public class TestClass {

    public static void main(String args[ ]) {
    Map<Integer,String> states= new Hashtable<Integer,String>();
    states.put(1, "INDIA");
    states.put(2, "USA");

    states.put(3, null);    //will throw NullPointerEcxeption at runtime

    System.out.println(states.get(1));
    System.out.println(states.get(2));
//  System.out.println(states.get(3));

    }
}

Bản đồ băm:

HashMap giống như Hashtable nhưng nó cũng chấp nhận cặp giá trị chính. Nó cho phép null cho cả khóa và giá trị. Hiệu suất của nó tốt hơn là tốt hơn HashTable, bởi vì nó làunsynchronized .

Thí dụ:

import java.util.HashMap;
import java.util.Map;

public class TestClass {

    public static void main(String args[ ]) {
    Map<Integer,String> states = new HashMap<Integer,String>();
    states.put(1, "INDIA");
    states.put(2, "USA");

    states.put(3, null);    // Okay
    states.put(null,"UK");

    System.out.println(states.get(1));
    System.out.println(states.get(2));
    System.out.println(states.get(3));

    }
}

5

HashMapđược mô phỏng và do đó có thể sử dụng trong GWT client codekhi Hashtablekhông.


Đó có phải là một mô tả toàn diện về sự khác biệt giữa hai apis?
IgorGanapolsky

Vâng (sic!). Đó là tất cả các nhà phát triển GWT cần biết về nó.
pong

5

Chủ đề cũ và cổ điển, chỉ muốn thêm blog hữu ích này giải thích điều này:

http://blog.manishchhabra.com/2012/08/the-5-main-differences-betwen-hashmap-and-hashtable/

Blog của Manish Chhabra

5 sự khác biệt chính giữa betwen HashMap và Hashtable

Cả HashMap và Hashtable đều triển khai giao diện java.util.Map nhưng có một số khác biệt mà các nhà phát triển Java phải hiểu để viết mã hiệu quả hơn. Kể từ nền tảng Java 2 v1.2, lớp Hashtable đã được trang bị thêm để triển khai giao diện Bản đồ, làm cho nó trở thành thành viên của Khung công tác thu thập Java.

  1. Một trong những khác biệt chính giữa HashMap và Hashtable là HashMap không được đồng bộ hóa trong khi Hashtable được đồng bộ hóa, điều đó có nghĩa là Hashtable an toàn cho luồng và có thể được chia sẻ giữa nhiều luồng nhưng HashMap không thể được chia sẻ giữa nhiều luồng mà không cần đồng bộ hóa. Java 5 đã giới thiệu ConcảnHashMap, là một thay thế của Hashtable và cung cấp khả năng mở rộng tốt hơn Hashtable trong Java. Đồ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, điều đó có nghĩa là bất kỳ luồng nào trước khi thực hiện cập nhật trên hashtable sẽ phải có được khóa trên đối tượng trong khi các luồng khác sẽ chờ khóa được phát hành.

  2. Lớp HashMap gần tương đương với Hashtable, ngoại trừ việc nó cho phép null. (HashMap cho phép giá trị null là khóa và giá trị trong khi Hashtable không cho phép null).

  3. Sự khác biệt đáng kể thứ ba giữa HashMap so với Hashtable là Iterator trong HashMap là một trình lặp không nhanh trong khi trình liệt kê cho Hashtable thì không và ném ConcurrencyModificationException 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 xóa bất kỳ phần tử nào ) phương pháp. Nhưng đây không phải là một hành vi được bảo đảm và sẽ được JVM thực hiện với nỗ lực cao nhất. Đây cũng là một sự khác biệt quan trọng giữa Enumutions và Iterator trong Java.

  4. Một điểm khác biệt đáng chú ý giữa Hashtable và HashMap là do tính an toàn của luồng và đồng bộ hóa Hashtable chậm hơn nhiều so với HashMap nếu được sử dụng trong môi trường luồng đơn. Vì vậy, nếu bạn không cần đồng bộ hóa và HashMap chỉ được sử dụng bởi một luồng, thì nó thực hiện Hashtable trong Java.

  5. HashMap không đảm bảo rằng thứ tự của bản đồ sẽ không đổi theo thời gian.

Lưu ý rằng HashMap có thể được đồng bộ hóa bởi

Map m = Collections.synchronizedMap(hashMap);

Tóm lại, có sự khác biệt đáng kể giữa Hashtable và HashMap trong Java, ví dụ như an toàn và tốc độ của luồng và dựa trên đó chỉ sử dụng Hashtable nếu bạn thực sự cần an toàn luồng, nếu bạn đang chạy Java 5, hãy cân nhắc sử dụng ConcảnHashMap trong Java.


ConcảnHashMap không được đồng bộ hóa đọc, trong khi Hashtable là. Vì vậy, nếu bạn có số lượng lớn các hoạt động đọc xảy ra đồng thời với ghi, Hashtable sẽ phục vụ bạn tốt hơn nếu bạn quan tâm đến tính toàn vẹn dữ liệu.
IgorGanapolsky

5

Cả HashMapHashtable đều được sử dụng để lưu trữ dữ liệu ở dạng khóa và giá trị. Cả hai đều sử dụng kỹ thuật băm để lưu trữ các khóa độc đáo. ut có nhiều sự khác biệt giữa các lớp HashMap và Hashtable được đưa ra dưới đây.

nhập mô tả hình ảnh ở đây


Tóm tắt hình ảnh đẹp!
Nadjib Mami
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.