CodeGym /Blog Java /Ngẫu nhiên /HashMap: đây là loại bản đồ gì?

HashMap: đây là loại bản đồ gì?

Xuất bản trong nhóm
CHÀO! Trong bài học này, chúng ta sẽ xem xét kỹ hơn về Java HashMap . Trước đây, chúng ta đã nghiên cứu cấu trúc dữ liệu trong đó các phần tử được lưu trữ dưới dạng chính chúng. Trong một mảng hoặc ArrayList / LinkedList , chúng tôi lưu trữ một số phần tử. Nhưng nếu nhiệm vụ của chúng ta thay đổi một chút thì sao?
HashMap: đây là loại bản đồ gì?  - 1
Hãy tưởng tượng nhiệm vụ sau: tạo danh sách 100 người lưu trữ tên và số hộ chiếu của từng người. Về nguyên tắc, điều này không quá khó. Ví dụ: bạn có thể nhập cả hai vào một chuỗi, sau đó tạo danh sách các chuỗi này: "Amelia Aguilar, 4211 717171". Nhưng giải pháp này có hai nhược điểm. Đầu tiên, chúng tôi có thể cần khả năng tìm kiếm theo số hộ chiếu. Và đây sẽ là vấn đề với định dạng lưu trữ thông tin này. Thứ hai, không có gì ngăn chúng tôi tạo ra hai người khác nhau có cùng số hộ chiếu. Và đây là thiếu sót nghiêm trọng nhất của giải pháp của chúng tôi. Điều này không bao giờ được phép xảy ra: không có hai người nào có cùng số hộ chiếu. Một cấu trúc dữ liệu mới đến với sự trợ giúp của chúng tôi: Bản đồ. Nó còn được gọi là "mảng kết hợp", nhưng thuật ngữ này không được sử dụng thường xuyên. Phổ biến hơn, nó được gọi là "từ điển" hoặc "bản đồ". :) Nó khác về cơ bản như thế nào so với các cấu trúc dữ liệu mà chúng ta đã xem xét trước đây? Trên hết, thực tế là dữ liệu trong Bản đồ được lưu trữ dưới dạng các cặp khóa-giá trị. Mọi thứ đều có thể đóng vai trò là khóa và giá trị: số, chuỗi hoặc đối tượng của các lớp khác. Hôm nay chúng ta sẽ nghiên cứu cách triển khai phổ biến nhất của lớp Bản đồ : Java HashMap . HashMap: đây là loại bản đồ gì?  - 2

Vậy chúng ta cần biết gì về HashMap trong Java?

Nó rất dễ dàng để tạo ra:

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();
}
Ở đây chúng tôi tạo một từ điển lưu trữ các phần tử dưới dạng các cặp "chuỗi số". Số sẽ đóng vai trò là khóa và chuỗi là giá trị. Ngoài ra, chúng tôi chỉ định loại khóa (Số nguyên) và loại giá trị (Chuỗi). Tại sao? Đầu tiên, khóa HashMap luôn là duy nhất. Điều này hoàn toàn phù hợp với chúng tôi, vì chúng tôi có thể sử dụng số hộ chiếu làm chìa khóa và tránh trùng lặp. Giá trị sẽ là một chuỗi có tên đầy đủ (những người khác nhau có thể có cùng tên; chúng tôi không có gì phải lo lắng). Thêm một cặp mới vào HashMap trông như thế này:

public class Main {

   public static void main(String[] args) {
       HashMap<Integer, String> passportsAndNames = new HashMap<>();

       passportsAndNames.put (212133, "Bridget Logan");
       passportsAndNames.put (162348, "Ivan the Great");
       passportsAndNames.put(8082771, "Donald John Trump");
       System.out.println(passportsAndNames);
   }
}
Chúng tôi sử dụng phương thức put() cho việc này. Ngoài ra, HashMap ghi đè phương thức toString() , vì vậy nó có thể được hiển thị trên bảng điều khiển. Đầu ra sẽ như sau: {212133=Bridget Logan, 8082771=Donald John Trump, 162348=Ivan the Great} Bây giờ, hãy xác minh xem các khóa có thực sự là duy nhất không? Hãy thử thêm một phần tử mới với khóa đã được sử dụng trong bản đồ:

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put (212133, "Bridget Logan");
   passportsAndNames.put (162348, "Ivan the Great");
   passportsAndNames.put(8082771, "Donald John Trump");
   passportsAndNames.put(162348, "Albert Kent");// This key has already been used
   System.out.println(passportsAndNames);
}
Kết quả: {212133=Bridget Logan, 8082771=Donald John Trump, 162348=Albert Kent} Như bạn có thể thấy, giá trị trước đó được liên kết với khóa 162348 đã bị ghi đè. Chúng tôi sử dụng thuật ngữ "chìa khóa" vì một lý do. Các giá trị trong HashMap được truy cập bằng cách sử dụng khóa chứ không phải theo cách khác. Không thể lấy khóa bằng cách sử dụng một giá trị vì các giá trị có thể không phải là duy nhất. Có thể thấy rõ điều này khi lấy hoặc xóa một phần tử khỏi HashMap :

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put (212133, "Bridget Logan");
   passportsAndNames.put (162348, "Ivan the Great");
   passportsAndNames.put(8082771, "Donald John Trump");

   String lidiaName = passportsAndNames.get(212133);
   System.out.println(lidiaName);

   passportsAndNames.remove(162348);
   System.out.println(passportsAndNames);
}
Để lấy một giá trị hoặc xóa một cặp khỏi từ điển, chúng ta phải chuyển đến get()remove() khóa duy nhất tương ứng với giá trị. Không giống như mảng và danh sách, HashMap trong Java không có chỉ số số: các giá trị được truy cập bằng khóa. Đầu ra bảng điều khiển: Bridget Logan {212133=Bridget Logan, 8082771=Donald John Trump} Các lớp ArrayListLinkedList cho phép chúng tôi kiểm tra xem danh sách có chứa bất kỳ phần tử cụ thể nào không. Java HashMap cho phép chúng tôi làm điều này. Hơn nữa, chúng ta có thể làm điều này cho cả hai thành viên của cặp: Đây là hàm containsKey() (kiểm tra khóa) và hàm containsValue()(kiểm tra một giá trị) các phương thức dành cho.

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put (212133, "Bridget Logan");
   passportsAndNames.put (162348, "Ivan the Great");
   passportsAndNames.put(8082771, "Donald John Trump");

   System.out.println(passportsAndNames.containsKey(11111));
   System.out.println(passportsAndNames.containsValue("Donald John Trump"));
}
Kết quả: false true Một tính năng tiện lợi khác của HashMap trong Java là bạn có thể lấy các danh sách riêng biệt của tất cả các khóa và tất cả các giá trị. Điều này được thực hiện với các phương thức keySet()values() :

public class Main {

   public static void main(String[] args) {
       HashMap<Integer, String> passportsAndNames = new HashMap<>();

       passportsAndNames.put (212133, "Bridget Logan");
       passportsAndNames.put (162348, "Ivan the Great");
       passportsAndNames.put(8082771, "Donald John Trump");

       Set keys = passportsAndNames.keySet();
       System.out.println("Keys: " + keys);

       ArrayList<String> values = new ArrayList<>(passportsAndNames.values());
       System.out.println("Values: " + values);
   }
}
Các khóa được trích xuất thành Set mà chúng tôi chưa đề cập đến. Nó đặc biệt ở chỗ không được chứa các phần tử lặp. Bây giờ, điều chính cần nhớ là danh sách tất cả các khóa có thể được truy xuất từ ​​HashMap vào một bộ sưu tập riêng biệt. Trong ví dụ này, chúng tôi đã lưu các giá trị vào một ArrayList bình thường . Đầu ra bảng điều khiển: Phím: [212133, 8082771, 162348] Giá trị: [Bridget Logan, Donald John Trump, Ivan the Great] Các phương thức size()clear() thực hiện chính xác điều tương tự như trong các cấu trúc trước đây mà chúng ta đã thảo luận: cái đầu tiên trả về số phần tử hiện có trong từ điển, cái thứ hai loại bỏ tất cả các phần tử.

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put (212133, "Bridget Logan");
   passportsAndNames.put (162348, "Ivan the Great");
   passportsAndNames.put(8082771, "Donald John Trump");

   System.out.println(passportsAndNames.size());
   passportsAndNames.clear();
   System.out.println(passportsAndNames);
}
Kết quả: 3 {} Để kiểm tra xem có ít nhất một phần tử trong HashMap của chúng ta hay không , chúng ta có thể sử dụng phương thức isEmpty() :

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put (212133, "Bridget Logan");
   passportsAndNames.put (162348, "Ivan the Great");
   passportsAndNames.put(8082771, "Donald John Trump");

   if (!passportsAndNames.isEmpty()) {

       System.out.println(passportsAndNames);
   }
}
Đầu ra: {212133=Bridget Logan, 8082771=Donald John Trump, 162348=Ivan the Great} Bây giờ chúng ta sẽ chỉ xuất ra bảng điều khiển sau khi kiểm tra sơ bộ. :) Một điểm thú vị nữa là hai Maps có thể được kết hợp thành một. Điều này được thực hiện bằng cách sử dụng phương thức putAll() . Chúng tôi gọi nó trên HashMap đầu tiên , chuyển phần thứ hai làm đối số và các phần tử từ phần thứ hai được thêm vào phần đầu tiên:

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();
   HashMap<Integer, String> passportsAndNames2 = new HashMap<>();

   passportsAndNames.put (212133, "Bridget Logan");
   passportsAndNames.put (162348, "Ivan the Great");
   passportsAndNames.put(8082771, "Donald John Trump");

   passportsAndNames2.put(917352, "Clifford Patrick");
   passportsAndNames2.put(925648, "Mitchell Salgado");

   passportsAndNames.putAll(passportsAndNames2);
   System.out.println(passportsAndNames);
}
Kết quả: {917352=Clifford Patrick, 212133=Bridget Logan, 8082771=Donald John Trump, 925648=Mitchell Salgado, 162348=Ivan Đại đế} Tất cả các cặp trong passportsAndNames2 đã được sao chép sang passportsAndNames . Bây giờ hãy xem xét một ví dụ phức tạp hơn. Cụ thể, lặp lại HashMap trong một vòng lặp.

for (Map.Entry<Integer, String> entry: passportsAndNames.entrySet()) {
   System.out.println(entry);
}
Lớp Map.Entry biểu thị cặp khóa-giá trị bên trong từ điển. Phương thức entrySet () trả về danh sách tất cả các cặp trong HashMap của chúng tôi . Bởi vì bản đồ của chúng tôi bao gồm các cặp Map.Entry này nên chúng tôi đang lặp lại các cặp chứ không phải các khóa hoặc giá trị riêng biệt. Kết quả: 212133=Bridget Logan 8082771=Donald John Trump 162348=Ivan Đại đế Ngoài ra, đừng quên nghiên cứu tài liệu chính thức của Oracle cho HashMap .
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION