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ị. Collection
s đượ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 HashMap
và Hashtable
. 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.2
Hashtable đượ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 " hash
collision
", 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).
« 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, HashMap
giả 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 = 8
chuyể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_THRESHOLD
UNTREEIFY_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 |
+--------------------+-----------+-------------+
Iterator
là 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ư Enumeration
là 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 ConcurrentMap
triể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 HashMapEntry
giá 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 Hashtable
như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
HashMap
cho 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 Hashtable
khô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 Hashtable
trong các ứng dụng đa luồng. Trường hợp như HashMap
không được đồng bộ nội bộ. Do đó, không an toàn khi sử dụng HashMap
trong 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 HashMap
bằ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 Hashtable
hơi chậm hơn so với HashMap
.
@Xem