JavaRush /Blog Java /Random-VI /HashMap trong Java - nó là loại bản đồ gì?

HashMap trong Java - nó là loại bản đồ gì?

Xuất bản trong nhóm
Xin chào! Hôm nay chúng ta sẽ nói về một cấu trúc dữ liệu khác - Bản đồ. Tên tiếng Nga chính thức của nó là “mảng kết hợp”, nhưng nó không được sử dụng thường xuyên. Các tùy chọn phổ biến hơn là “từ điển”, “bản đồ” hoặc (thường xuyên nhất) tiếng lóng tiếng Anh “bản đồ” :) Bên trong Bản đồ, dữ liệu được lưu trữ ở định dạng “khóa” - “giá trị”, nghĩa là theo cặp. Cả khóa và giá trị đều có thể là bất kỳ đối tượng nào—số, chuỗi hoặc đối tượng của các lớp khác.

Bản đồ khác với các cấu trúc dữ liệu khác như thế nào

Trước đây, chúng ta đã xem xét cấu trúc dữ liệu trong đó các phần tử được lưu trữ riêng lẻ. Trong một mảng, hoặc ArrayList / LinkedList , chúng ta lưu trữ một số phần tử nhất định. Nhưng nếu nhiệm vụ của chúng ta thay đổi một chút thì sao? Ví dụ: hãy tưởng tượng rằng chúng ta phải đối mặt với nhiệm vụ tạo một danh sách gồm 100 người, trong đó họ tên đầy đủ và số hộ chiếu của người đó sẽ được lưu trữ. Về nguyên tắc, nó không khó lắm. Ví dụ: bạn có thể khớp cả hai trong một dòng và tạo danh sách các dòng như sau: “Anna Ivanovna Reshetnikova, 4211 717171.” Nhưng giải pháp này có hai nhược điểm. Đầu tiên, chúng ta có thể cần chức năng tìm kiếm hộ chiếu. Và với định dạng lưu trữ thông tin này, điều này sẽ có vấn đề. Và thứ hai, không có gì ngăn cản chúng ta tạo ra hai người khác nhau có cùng số hộ chiếu. Và đây là nhược điểm nghiêm trọng nhất của giải pháp của chúng tôi. Những tình huống như vậy cần được loại trừ hoàn toàn, không có hai người có cùng số hộ chiếu. Ở đây, Bản đồ và các tính năng được khai báo của nó sẽ hỗ trợ chúng tôi (lưu trữ dữ liệu theo cặp ở định dạng “khóa”-”giá trị”). Hãy xem cách triển khai Map phổ biến nhất - lớp Java HashMap .HashMap - đây là loại bản đồ gì?  - 1

Tạo HashMap trong Java và làm việc với lớp

Việc thực hiện này rất đơn giản để tạo:
public static void main(String[] args) {

   HashMap<Integer, String> passportsAndNames = new HashMap<>();

}
Ở đây chúng tôi đã tạo một từ điển trong đó các phần tử sẽ được lưu trữ ở định dạng “chuỗi số”. Số sẽ là khóa và chuỗi sẽ là giá trị. Chúng tôi cũng chỉ ra loại khóa nào chúng tôi sẽ có ( Integer) và loại giá trị nào chúng tôi sẽ có ( String). Tại sao cái này rất? Đầu tiên, khóa trong HashMap luôn là duy nhất . Điều này sẽ rất hữu ích cho 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. Và dòng có tên đầy đủ sẽ đóng vai trò như một giá trị (tên đầy đủ của những người khác nhau có thể dễ dàng được lặp lại, điều đó không có gì sai đối với chúng tôi).

Thêm một cặp mới vào HashMap

Nhiệm vụ này trông như thế này:
public class Main {

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


       passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
       passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
       passportsAndNames.put(8082771, "Donald John Trump");
       System.out.println(passportsAndNames);

   }

}
Phương pháp này được sử dụng cho việc này put(). Ngoài ra, HashMap có một phương thức được ghi đè toString()để có thể in ra bảng điều khiển. Kết quả đầu ra sẽ như thế này: {212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump, 162348=Ivan Mikhailovich Serebrykov}

Các tính năng của Khóa HashMap

Bây giờ hãy kiểm tra xem các phím có thực sự độc đáo không? Hãy thử thêm một phần tử mới bằng một khóa đã có trong bản đồ:
public static void main(String[] args) {

   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
   passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
   passportsAndNames.put(8082771, "Donald John Trump");
   passportsAndNames.put(162348, "Viktor Mikhailovich Stychkin");//repeat key

   System.out.println(passportsAndNames);

}
Đầu ra: {212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump, 162348=Viktor Mikhailovich Stychkin} Phần tử trước đó có khóa 162348, như bạn có thể thấy, đã bị ghi đè. “Chìa khóa” được gọi là chìa khóa là có lý do. Các giá trị trong HashMap được truy cập bằng khóa (nhưng không phải ngược lại - không thể lấy khóa theo giá trị, vì các giá trị có thể bị trùng lặp). Điều này được thấy rõ trong các ví dụ về việc lấy một phần tử, cũng như 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, "Lydia Arkadievna Bublikova");
   passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
   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 chính xác khóa duy nhất tương ứng với giá trị này cho get()các phương thức . Không có chỉ mục số, như trong mảng hoặc danh sách, trong HashMap - giá trị được truy cập bằng khóa. Đầu ra của bảng điều khiển: Lidiya Arkadyevna Bublikova {212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump}remove()

Kiểm tra sự hiện diện của khóa và giá trị

Trong các lớp ArrayListLinkedList , chúng ta có thể kiểm tra xem danh sách có chứa một phần tử cụ thể hay không. HashMap cũng cho phép bạn thực hiện việc này và đối với cả hai phần của cặp: nó có các phương thức containsKey()(kiểm tra sự hiện diện của khóa) và containsValue()(kiểm tra sự hiện diện của một giá trị).
public static void main(String[] args) {

   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
   passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
   passportsAndNames.put(8082771, "Donald John Trump");


   System.out.println(passportsAndNames.containsKey(11111));
   System.out.println(passportsAndNames.containsValue("Donald John Trump"));

}
Đầu ra: sai đúng

Lấy danh sách tất cả các khóa và giá trị

Một tính năng tiện lợi khác của HashMap là bạn có thể lấy riêng danh sách tất cả các khóa và tất cả các giá trị . Đối với điều này, các phương pháp keySet()và được sử dụng values():
public class Main {

   public static void main(String[] args) {

       HashMap<Integer, String> passportsAndNames = new HashMap<>();

       passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
       passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
       passportsAndNames.put(8082771, "Donald John Trump");

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

       ArrayList<String> values = new ArrayList<>(passportsAndNames.values());
       System.out.println("Values: " + values);

   }

}
Các phím được trích xuất vào bộ sưu tập Set. Điểm đặc biệt của nó là không thể chứa các phần tử lặp lại. Bây giờ điều chính cần nhớ là danh sách tất cả các khóa có thể được đưa ra khỏi HashMap thành một bộ sưu tập riêng. Trong ví dụ, chúng tôi đã lưu các giá trị thành ArrayList. Đầu ra của bảng điều khiển: Khóa: [212133, 8082771, 162348] Giá trị: [Lidiya Arkadyevna Bublikova, Donald John Trump, Ivan Mikhailovich Serebrykov] Các phương thức size()thực hiện clear()chính xác điều tương tự như trong các cấu trúc trước đó mà chúng ta đã trải qua: cấu trúc đầu tiên trả về một phần tử số trong từ điển ở thời điểm hiện tại, từ thứ hai sẽ xóa tất cả các phần tử.
public static void main(String[] args) {

   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
   passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
   passportsAndNames.put(8082771, "Donald John Trump");

   System.out.println(passportsAndNames.size());
   passportsAndNames.clear();
   System.out.println(passportsAndNames);

}
Đầu ra: 3 {} Để kiểm tra xem HashMap của chúng ta có ít nhất một phần tử 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, "Lydia Arkadievna Bublikova");
   passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
   passportsAndNames.put(8082771, "Donald John Trump");

   if (!passportsAndNames.isEmpty()) {

       System.out.println(passportsAndNames);

   }

}
Đầu ra: {212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump, 162348=Ivan Mikhailovich Serebrykov} Bây giờ chúng tôi sẽ chỉ xuất ra bảng điều khiển sau khi xác minh sơ bộ :)

Kết hợp hai bản đồ thành một

Một điểm thú vị khác là hai bản đồ có thể được kết hợp thành một . Có một phương pháp cho việc này 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 sẽ đượ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, "Lydia Arkadievna Bublikova");
   passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
   passportsAndNames.put(8082771, "Donald John Trump");

   passportsAndNames2.put(917352, "Alexey Andreevich Ermakov");
   passportsAndNames2.put(925648, "Maxim Olegovich Arkharov");


   passportsAndNames.putAll(passportsAndNames2);
   System.out.println(passportsAndNames);

}
Đầu ra: {917352=Alexey Andreevich Ermkov, 212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump, 925648=Maxim Olegovich Arkharov, 162348=Ivan Mikhailovich Serebrykov} Tất cả các thành phần của PassportsAndNames2 đã được sao chép vào PassportsAndNames . Bây giờ hãy xem một ví dụ phức tạp hơn. Cụ thể là lặp lại HashMap trong một vòng lặp.
for (Map.Entry entry: passportsAndNames.entrySet()) {

   System.out.println(entry);

}
Giao diện Map.Entrychỉ có nghĩa là một cặp khóa-giá trị bên trong từ điển. Phương thức này entrySet()trả về danh sách tất cả các cặp trong HashMap của chúng tôi (vì bản đồ của chúng tôi chỉ bao gồm các cặp Entry như vậy nên chúng tôi 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 luận: 212133=Lidiya Arkadyevna Bublikova 8082771=Donald John Trump 162348=Ivan Mikhailovich Serebrykov Lưu bài viết này cho tương lai: https://habr.com/ru/post/128017/ Bây giờ còn quá sớm để đọc nó, nhưng trong tương lai , khi bạn bắt đầu sử dụng HashMap, nó sẽ giúp bạn hiểu cách cấu trúc dữ liệu này hoạt động từ bên trong. Ngoài ra, đừng quên xem tài liệu chính thức của Oracle trên HashMap.
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION