HashMap là một cấu trúc dữ liệu quan trọng trong Java, được sử dụng rộng rãi để lưu trữ và quản lý dữ liệu theo cặp khóa-giá trị. Bài viết này sẽ cung cấp một cái nhìn toàn diện về HashMap, từ khái niệm cơ bản, nguyên lý hoạt động, các thao tác thường dùng, đến ứng dụng thực tế, giúp bạn nắm vững kiến thức và áp dụng hiệu quả trong các dự án lập trình.
Mục Lục
HashMap là gì?
HashMap là một implementation của interface Map
trong Java Collections Framework. Interface Map
định nghĩa một cấu trúc dữ liệu cho phép ánh xạ giữa các khóa (keys) và các giá trị (values). Mỗi khóa là duy nhất và được liên kết với một giá trị cụ thể.
Interface Map:
Map
là một interface trong Java Collections Framework, định nghĩa các phương thức để lưu trữ và truy xuất dữ liệu theo cặp khóa-giá trị.- Các
class
triển khaiMap
bao gồm:Hashtable
: Không cho phép khóa hoặc giá trịnull
, hỗ trợ đồng bộ hóa (thread-safe), nhưng hiệu năng kém hơnHashMap
.HashMap
: Cho phép khóa và giá trịnull
, không hỗ trợ đồng bộ hóa (không thread-safe), thứ tự các phần tử không được đảm bảo.TreeMap
: Các phần tử được sắp xếp theo thứ tự khóa tự nhiên hoặc theo mộtComparator
được cung cấp.LinkedHashMap
: Duy trì thứ tự chèn của các phần tử.
Nguyên lý hoạt động của HashMap
HashMap hoạt động dựa trên nguyên lý hashing.
Hashing là gì?
Hashing là một quá trình chuyển đổi một đối tượng thành một giá trị số nguyên duy nhất, gọi là hash code. Giá trị này được sử dụng làm chỉ mục để lưu trữ và truy xuất đối tượng trong HashMap.
Cách HashMap hoạt động:
- Khi một cặp khóa-giá trị được thêm vào HashMap, khóa được sử dụng để tính toán hash code.
- Hash code này được sử dụng để xác định vị trí (bucket) trong mảng nội bộ của HashMap, nơi cặp khóa-giá trị sẽ được lưu trữ.
- Nếu có nhiều khóa có cùng hash code (xảy ra collision), các cặp khóa-giá trị sẽ được lưu trữ trong cùng một bucket dưới dạng một danh sách liên kết (linked list) hoặc cây (tree).
- Khi tìm kiếm một giá trị dựa trên khóa, khóa được sử dụng để tính toán hash code, và bucket tương ứng được xác định.
- HashMap sau đó duyệt qua danh sách liên kết hoặc cây trong bucket để tìm khóa phù hợp và trả về giá trị tương ứng.
Đặc điểm chính của HashMap:
- Không cho phép các khóa trùng lặp (các giá trị có thể trùng lặp).
- Cho phép khóa và giá trị
null
. - Không đảm bảo thứ tự của các phần tử.
- Không hỗ trợ đồng bộ hóa (không thread-safe).
Các thao tác cơ bản với HashMap
1. Tạo mới HashMap
Để tạo một đối tượng HashMap mới, bạn có thể sử dụng cú pháp sau:
import java.util.HashMap;
// Tạo một HashMap với khóa và giá trị là String
HashMap<String, String> hashMap0 = new HashMap<>();
// Tạo một HashMap với khóa là Integer và giá trị là Float
HashMap<Integer, Float> hashMap1 = new HashMap<>();
// Tạo một HashMap với khóa là String và giá trị là Double, có kích thước ban đầu là 10
HashMap<String, Double> hashMap2 = new HashMap<>(10);
// Tạo một HashMap từ một Collection khác (ví dụ: TreeMap)
HashMap<String, Integer> hashMap4 = new HashMap<>(new TreeMap<>());
2. Thêm phần tử (Entry) vào HashMap
Để thêm một cặp khóa-giá trị vào HashMap, sử dụng phương thức put(key, value)
:
HashMap<String, String> dictionary = new HashMap<>();
dictionary.put("Hardware", "Phần cứng");
dictionary.put("Software", "Phần mềm");
dictionary.put("College", "Trường Đại Học");
dictionary.put("Programmer", "Lập Trình Viên");
dictionary.put("Compile", "Biên Dịch");
dictionary.put("Error", "Lỗi");
3. Sửa giá trị (Value) của một phần tử (Entry) trong HashMap
Để thay đổi giá trị của một khóa đã tồn tại, sử dụng phương thức replace(key, newValue)
:
HashMap<String, String> studentClass = new HashMap<>();
studentClass.put("DoanDucTin", "Class_SE1403");
studentClass.replace("DoanDucTin", "NewClass_SE1401");
4. Xóa một phần tử (Entry) ra khỏi HashMap
Để xóa một phần tử dựa vào khóa, sử dụng phương thức remove(key)
:
HashMap<String, String> errors = new HashMap<>();
errors.put("Error", "Lỗi");
errors.remove("Error");
5. Hiển thị toàn bộ phần tử (Entry) của HashMap
Cách 1: Sử dụng EntrySet
Phương thức entrySet()
trả về một Set
chứa tất cả các Entry
(cặp khóa-giá trị) trong HashMap.
HashMap<String, String> dictionary = new HashMap<>();
dictionary.put("Hardware", "Phần cứng");
dictionary.put("Software", "Phần mềm");
Set<Map.Entry<String, String>> entrySet = dictionary.entrySet();
for (Map.Entry<String, String> entry : entrySet) {
System.out.println(entry.getKey() + " -> " + entry.getValue());
}
Bạn cũng có thể hiển thị toàn bộ khóa hoặc giá trị:
// In toàn bộ key ra màn hình
for (String key : dictionary.keySet()) {
System.out.println(key);
}
// In toàn bộ giá trị ra màn hình
for (String value : dictionary.values()) {
System.out.println(value);
}
Cách 2: Sử dụng Iterator
Iterator
là một interface cho phép duyệt qua các phần tử của một collection.
import java.util.Iterator;
import java.util.Map;
import java.util.HashMap;
HashMap<String, String> dictionary = new HashMap<>();
dictionary.put("Hardware", "Phần cứng");
dictionary.put("Software", "Phần mềm");
Iterator<Map.Entry<String, String>> iterator = dictionary.entrySet().iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
6. Lấy giá trị (Value) khi biết khóa (Key)
Sử dụng phương thức get(key)
để lấy giá trị tương ứng với một khóa.
HashMap<String, String> studentClass = new HashMap<>();
studentClass.put("DoanDucTin", "Class_SE1403");
System.out.println(studentClass.get("DoanDucTin")); // Console ->: Class_SE1403
Một số phương thức khác
Phương Thức | Mô tả sơ lược |
---|---|
void clear() |
Xóa tất cả các phần tử của HashMap. |
Object clone() |
Trả về một bản sao của HashMap. |
boolean containsKey(Object key) |
Kiểm tra nếu HashMap chứa một phần tử có khóa được chỉ định. |
boolean containsValue(Object value) |
Kiểm tra nếu HashMap chứa một phần tử có giá trị được chỉ định. |
boolean isEmpty() |
Kiểm tra HashMap trống hay không. |
void putAll(Map t) |
Sao chép các phần tử của Map vào HashMap. |
int size() |
Trả về số phần tử đang tồn tại bên trong HashMap. |
Ứng dụng của HashMap
HashMap có rất nhiều ứng dụng trong lập trình, một vài ví dụ điển hình:
-
Từ điển: Sử dụng HashMap để lưu trữ các cặp từ-nghĩa, giúp tra cứu nhanh chóng.
-
Quản lý đối tượng: Sử dụng HashMap để quản lý các đối tượng dựa trên một khóa định danh, ví dụ: quản lý thông tin sinh viên dựa trên mã số sinh viên.
-
Cache: Lưu trữ dữ liệu tạm thời để tăng tốc độ truy cập.
-
Đếm tần suất xuất hiện của các phần tử: Sử dụng HashMap để đếm số lần xuất hiện của mỗi phần tử trong một mảng hoặc danh sách.
Tổng kết
Bài viết này đã cung cấp một cái nhìn tổng quan về HashMap trong Java, bao gồm khái niệm, nguyên lý hoạt động, các thao tác cơ bản và ứng dụng thực tế. Hiểu rõ về HashMap sẽ giúp bạn viết code hiệu quả hơn và giải quyết các vấn đề lập trình một cách dễ dàng hơn. HashMap là một kiến thức quan trọng mà các nhà tuyển dụng thường sử dụng để đánh giá trình độ của ứng viên, vì vậy hãy nắm vững kiến thức này để chuẩn bị tốt cho các buổi phỏng vấn.