JavaRush /Blog Java /Random-VI /Giải đáp các câu hỏi phổ biến nhất về giao diện Bản đồ

Giải đáp các câu hỏi phổ biến nhất về giao diện Bản đồ

Xuất bản trong nhóm
Xin chào! Hôm nay chúng tôi sẽ đưa ra câu trả lời cho những câu hỏi phổ biến nhất về Bản đồ, nhưng trước tiên, hãy nhớ nó là gì. Giải đáp những thắc mắc phổ biến nhất về giao diện Map - 1Bản đồ là cấu trúc dữ liệu chứa một tập hợp các cặp khóa-giá trị. Cấu trúc dữ liệu của nó giống như một cuốn từ điển, đó là lý do tại sao nó thường được gọi như vậy. Đồng thời, Map là một giao diện và trong jdk tiêu chuẩn, nó chứa các phần triển khai chính: Hashmap, LinkedHashMap, Hashtable, TreeMap. Triển khai được sử dụng nhiều nhất là Hashmap, vì vậy chúng tôi sẽ sử dụng nó trong các ví dụ của mình. Đây là cách tạo và điền bản đồ tiêu chuẩn trông như thế nào:
Map<Integer, String> map = new HashMap<>();
map.put(1, "string 1");
map.put(2, "string 2");
map.put(3, "string 3");
Và đây là cách lấy giá trị theo key:
String string1 = map.get(1);
String string2 = map.get(2);
String string3 = map.get(3);
Nếu tất cả những điều trên đều rõ ràng, hãy chuyển sang câu trả lời của chúng tôi cho các câu hỏi phổ biến!

0. Cách lặp qua tất cả các giá trị Bản đồ

Lặp lại các giá trị là thao tác phổ biến nhất bạn thực hiện với bản đồ. Tất cả các cặp khóa-giá trị được lưu trữ trong giao diện Map.Entry nội bộ và để có được chúng, bạn cần gọi phương thức entrySet(). Nó trả về một Tập hợp các cặp có thể được lặp qua:
for(Map.Entry<Integer, String> entry: map.entrySet()) {
   // get key
   Integer key = entry.getKey();
   // get value
   String value = entry.getValue();
}

Или используя итератор:
Iterator<Map.Entry<Integer, String>> itr = map.entrySet().iterator();
while(itr.hasNext()) {
   Map.Entry<Integer, String> entry =  itr.next();
   // get key
   Integer key = entry.getKey();
   // get value
   String value = entry.getValue();
}

1. Cách chuyển Bản đồ thành Danh sách

Giao diện Map có 3 phương thức trả về danh sách các phần tử:
  • keySet() - trả về một Bộ khóa;
  • value() - trả về Tập hợp các giá trị;
  • entrySet() - trả về Tập hợp các bộ khóa-giá trị.
Nếu bạn nhìn vào các hàm tạo của lớp ArrayList, bạn sẽ nhận thấy rằng có một hàm tạo với đối số kiểu Collection. Vì Set là hậu duệ của Collection nên kết quả của tất cả các phương thức trên có thể được chuyển đến hàm tạo của lớp ArrayList. Vì vậy chúng ta sẽ tạo danh sách mới và điền vào chúng các giá trị từ Map:
// key list
List<Integer> keyList = new ArrayList<>(map.keySet());
// value list
List<String> valueList = new ArrayList<>(map.values());
// key-value list
List<Map.Entry<Integer, String>> entryList = new ArrayList<>(map.entrySet());

2. Cách sắp xếp key bản đồ

Sắp xếp bản đồ cũng là một thao tác khá phổ biến trong lập trình. Bạn có thể làm điều này theo nhiều cách:
  1. Đặt Map.Entry vào một danh sách và sắp xếp nó bằng Comparator .

    Trong bộ so sánh, chúng ta sẽ chỉ so sánh các khóa của các cặp:

    List> list = new ArrayList(map.entrySet());
    Collections.sort(list, new Comparator<Map.Entry<Integer, String>>() {
       @Override
       public int compare(Map.Entry<Integer, String> o1, Map.Entry<Integer, String> o2) {
           return o1.getKey() - o2.getKey();
       }
    });
    

    Nếu bạn hiểu lambdas, mục này có thể được rút ngắn đáng kể:

    Collections.sort(list, Comparator.comparingInt(Map.Entry::getKey));
  2. Sử dụng SortedMap, hay chính xác hơn là cách triển khai của nó TreeMap, sử dụng Bộ so sánh trong hàm tạo của nó. Bộ so sánh này sẽ được áp dụng cho các khóa bản đồ, vì vậy các khóa phải là các lớp triển khai giao diện Comparable:

    SortedMap<Integer, String> sortedMap = new TreeMap<>(new Comparator<Integer>() {
       @Override
       public int compare(Integer o1, Integer o2) {
           return o1 - o2;
       }
    });

    Và tất nhiên, mọi thứ đều có thể được viết lại bằng lambdas:

    SortedMap<Integer, String> sortedMap = new TreeMap<>(Comparator.comparingInt(o -> o));

    Không giống như phương pháp đầu tiên, sử dụng SortedMap, chúng tôi sẽ luôn lưu trữ dữ liệu ở dạng được sắp xếp.

3. Cách sắp xếp giá trị bản đồ

Ở đây, bạn nên sử dụng cách tiếp cận tương tự như cách tiếp cận đầu tiên đối với khóa - lấy danh sách các giá trị và sắp xếp chúng trong danh sách:
List <Map.Entry<Integer, String>> valuesList = new ArrayList(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<Integer, String>>() {
   @Override
   public int compare(Map.Entry<Integer, String> o1, Map.Entry<Integer, String> o2) {
       return o1.getValue().compareTo(o2.getValue());
   }
});
Và lambda cho việc này trông như thế này:
Collections.sort(list, Comparator.comparing(Map.Entry::getValue));

4. Sự khác biệt giữa HashMap, TreeMap và Hashtable là gì

Như đã đề cập trước đó, có 3 cách triển khai chính của giao diện Bản đồ. Mỗi người trong số họ có những đặc điểm riêng:
  1. Thứ tự của các phần tử. HashMapHashtablekhông đảm bảo rằng các mục sẽ được lưu trữ theo thứ tự chúng được thêm vào. Ngoài ra, chúng không đảm bảo rằng thứ tự của các phần tử sẽ không thay đổi theo thời gian. Đổi lại, TreeMapnó đảm bảo việc lưu trữ các phần tử theo thứ tự chúng được thêm vào hoặc theo một bộ so sánh nhất định.

  2. Các giá trị hợp lệ. HashMapcho phép bạn có một khóa và một giá trị null, HashTablekhông. TreeMap chỉ có thể sử dụng giá trị null nếu bộ so sánh cho phép. Không sử dụng bộ so sánh (bằng cách lưu trữ các cặp theo thứ tự chúng được thêm vào), null không được phép.

  3. Đồng bộ hóa. Chỉ HashTableđồng bộ thôi, còn lại thì không. Nếu bản đồ không được truy cập bởi các luồng khác nhau, bạn nên sử dụng HashMap thay vì HashTable.

Và một so sánh chung về việc triển khai:
Bản đồ băm Bảng băm Bản đồ cây
Thứ tự các phần tử KHÔNG KHÔNG Đúng
null làm giá trị Đúng KHÔNG Không thực sự
An toàn chủ đề KHÔNG Đúng KHÔNG
Độ phức tạp của thuật toán tìm kiếm phần tử O(1) O(1) O(logn)
Cấu trúc dữ liệu dưới mui xe bảng băm bảng băm cây đỏ đen

5. Cách tạo bản đồ hai chiều

Đôi khi cần phải sử dụng cấu trúc dữ liệu trong đó cả khóa và giá trị sẽ là duy nhất, nghĩa là bản đồ sẽ chứa các cặp khóa-khóa. Cấu trúc dữ liệu này cho phép bạn tạo “chế độ xem/tìm kiếm đảo ngược” trên bản đồ. Nghĩa là, chúng ta có thể tìm thấy khóa theo giá trị của nó, cấu trúc dữ liệu này được gọi là bản đồ hai chiều, thật không may, cấu trúc này không được JDK hỗ trợ. Nhưng may mắn thay, việc triển khai nó có thể được tìm thấy trong các thư viện Guava hoặc Bộ sưu tập chung của Apache. Ở đó nó được gọi lần lượt là BidiMap và BiMap. Những triển khai này áp đặt các hạn chế về tính duy nhất của khóa và giá trị. Điều này tạo ra mối quan hệ một-một.

6. Cách tạo Map trống

Có hai cách để tạo một bản đồ trống:
  1. Khởi tạo đối tượng bình thường:

    Map<Integer, String> emptyMap = new HashMap<>();
  2. Tạo một bản đồ trống bất biến:

    Map<Integer, String> emptyMap =  Collections.emptyMap();
Khi chúng tôi cố gắng thêm dữ liệu vào bản đồ như vậy, chúng tôi sẽ nhận được: UnsupportedOperationExceptionngoại lệ. Trong bài viết này, chúng tôi đã xem xét các câu hỏi phổ biến nhất mà bạn có thể gặp phải khi sử dụng giao diện Bản đồ.
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION