JavaRush /Blog Java /Random-VI /9 câu hỏi hàng đầu về bản đồ trong Java
Treefeed
Mức độ

9 câu hỏi hàng đầu về bản đồ trong Java

Xuất bản trong nhóm
Hãy nhớ lại rằng Bản đồ là dữ liệu có cấu trúc bao gồm một tập hợp các cặp khóa-giá trị và mỗi khóa chỉ có thể được sử dụng một lần trong một Bản đồ. Chủ đề này bao gồm 9 câu hỏi cơ bản về cách sử dụng Map trong Java và các lớp được triển khai của nó. Để đơn giản, tôi sẽ sử dụng những khái quát hóa trong các ví dụ . Vì vậy, tôi sẽ viết đơn giản là Map, không chỉ định Map specifier. Nhưng bạn có thể giả sử rằng cả hai giá trị của KV đều có thể so sánh được, điều đó có nghĩa là K mở rộng ComparableV cũng mở rộng Comparable .9 câu hỏi hàng đầu về bản đồ trong Java - 1

0. Chuyển đổi bản đồ thành danh sách

Trong Java, giao diện Map cung cấp ba loại bộ sưu tập: bộ khóa, bộ giá trị và bộ khóa-giá trị. Tất cả chúng có thể được chuyển thành Danh sách bằng cách sử dụng hàm tạo hoặc phương thức addAll(). Đoạn mã sau đây trình bày cách tạo một ArrayList từ Bản đồ.
// list of keys
List keyList = new ArrayList(Map.keySet());
//list of values
List valueList = new ArrayList(Map.valueSet());
//list key-value
List entryList = new ArrayList(Map.entrySet());

1. Lặp qua tất cả các giá trị trong Map

Đi qua từng cặp khóa-giá trị là quy trình cơ bản, cơ bản nhất để đi qua Bản đồ. Trong Java, mỗi cặp được lưu trữ trong trường Map có tên Map.Entry . Map.entrySet()trả về một tập hợp khóa-giá trị, vì vậy cách hiệu quả nhất để lặp qua tất cả các giá trị của Bản đồ sẽ là:
for(Entry entry: Map.entrySet()) {
  //get the key
  K key = entry.getKey();
  //get value
  V value = entry.getValue();
}
Chúng ta cũng có thể sử dụng Iterator, đặc biệt là trong các phiên bản trẻ hơn JDK 1.5
Iterator itr = Map.entrySet().iterator();
while(itr.hasNext()) {
  Entry entry = itr.next();
  //get the key
  K key = entry.getKey();
  //get value
  V value = entry.getValue();
}

2. Đặt hàng bản đồ theo phím

Sắp xếp Bản đồ theo phím là một thủ tục thường được sử dụng khác. Cách đầu tiên là thêm Map.Entry vào danh sách và sắp xếp bằng bộ so sánh sắp xếp theo giá trị.
List list = new ArrayList(Map.entrySet());
Collections.sort(list, new Comparator() {

  @Override
  public int compare(Entry e1, Entry e2) {
    return e1.getKey().compareTo(e2.getKey());
  }
});
Một cách khác: sử dụng SortedMap , ngoài ra, nó còn sắp xếp các khóa của nó theo thứ tự. Tuy nhiên, tất cả các khóa phải thể hiện Có thể so sánh hoặc được bộ so sánh chấp nhận. Một trong những lớp được triển khai SortedMapTreeMap . Hàm tạo của nó chấp nhận một bộ so sánh. Đoạn mã sau đây cho thấy cách biến một cái bình thường Mapthành một cái có thứ tự.
SortedMap sortedMap = new TreeMap(new Comparator() {

  @Override
  public int compare(K k1, K k2) {
    return k1.compareTo(k2);
  }

});
sortedMap.putAll(Map);

3. Bản đồ thứ tự theo giá trị

Việc thêm Bản đồ vào danh sách rồi sắp xếp nó sẽ hoạt động trong trường hợp này, nhưng lần này bạn cần sử dụng Entry.getValue(). Mã bên dưới gần giống như mã trước đây.
List list = new ArrayList(Map.entrySet());
Collections.sort(list, new Comparator() {

  @Override
  public int compare(Entry e1, Entry e2) {
    return e1.getValue().compareTo(e2.getValue());
  }

});
Chúng ta vẫn có thể sử dụng nó SortedMaptrong trường hợp này, nhưng chỉ khi các giá trị là duy nhất. Trong trường hợp này, bạn có thể biến cặp khóa-giá trị thành khóa-giá trị. Giải pháp này có những hạn chế nghiêm trọng và không được tôi khuyến nghị.

4. Khởi tạo Bản đồ tĩnh/bất biến

Khi bạn muốn một Bản đồ không thể thay đổi, cách tốt nhất là sao chép nó vào một Bản đồ bất biến. Kỹ thuật lập trình phòng thủ này sẽ giúp bạn tạo Bản đồ không chỉ an toàn khi sử dụng mà còn an toàn theo luồng. Để khởi tạo Bản đồ tĩnh/không thay đổi, chúng ta có thể sử dụng trình khởi tạo static(xem bên dưới). Vấn đề với đoạn mã này là mặc dù khai báo một Map là static final, chúng ta vẫn có thể làm việc với nó sau khi khởi tạo, ví dụ Test.Map.put(3,"three");. Vì vậy, nó không phải là bất biến thực sự. Để tạo Bản đồ bất biến bằng cách sử dụng trình khởi tạo tĩnh, chúng ta cần một lớp siêu ẩn danh mà chúng ta sẽ thêm vào Bản đồ bất biến ở bước khởi tạo cuối cùng. Vui lòng xem phần thứ hai của mã. Khi một ngoại lệ UnsupportedOperationException được ném ra nếu bạn chạy Test.Map.put(3,"three");.
public class Test {

  private static final Map Map;
  static {
    Map = new HashMap();
    Map.put(1, "one");
    Map.put(2, "two");
  }
}
public class Test {

  private static final Map Map;
  static {
    Map aMap = new HashMap();
    aMap.put(1, "one");
    aMap.put(2, "two");
    Map = Collections.unmodifiableMap(aMap);
  }
}
Thư viện Guava cũng hỗ trợ nhiều cách khác nhau để khởi tạo các bộ sưu tập tĩnh và bất biến. Để tìm hiểu thêm về lợi ích của tiện ích bộ sưu tập bất biến của Guava, hãy xem phần Bộ sưu tập bất biến trong Hướng dẫn sử dụng Guava .

5. Sự khác biệt giữa HashMap, TreeMap và Hashtable

Có ba cách triển khai chính của giao diện Map trong Java: HashMap , TreeMapHashtable . Sự khác biệt chính như sau:
  • Thứ tự đi qua . HashMap và HashTable không đảm bảo thứ tự của Bản đồ; đặc biệt, họ không đảm bảo rằng thứ tự sẽ được giữ nguyên theo thời gian. Nhưng TreeMapnó sẽ sắp xếp tất cả các giá trị theo "thứ tự tự nhiên" của các phím hoặc bằng một bộ so sánh.
  • Cặp khóa-giá trị hợp lệ. HashMapcho phép bạn có khóa null và giá trị null. HashTablekhông cho phép khóa null hoặc giá trị null. Nếu TreeMapthứ tự tự nhiên được sử dụng hoặc bộ so sánh không cho phép khóa null, một ngoại lệ sẽ được đưa ra.
  • Đồng bộ hóa . Chỉ HashTableđồng bộ thôi, còn lại thì không. Tuy nhiên, "nếu không cần triển khai an toàn theo luồng thì nên sử dụng " HashMapthay thế HashTable.
So sánh chi tiết hơn
.                       | HashMap | HashTable | TreeMap
-------------------------------------------------------

Упорядочивание          |нет      |нет        | да
null в ключ-meaning    | да-да   | нет-нет   | нет-да
синхронизировано        | нет     | да        | нет
производительность      | O(1)    | O(1)      | O(log n)
воплощение              | корзины | корзины   | красно-чёрное дерево
Đọc thêm về mối quan hệ giữa HashMap và . Bản đồ cây so với Bảng băm so với LinkedHashMap .

6. Bản đồ với tìm kiếm/xem ngược

Đôi khi, chúng ta cần một tập hợp các cặp khóa-khóa, có nghĩa là các giá trị cũng là duy nhất như các khóa (mẫu một-một). Tính nhất quán này cho phép bạn tạo "chế độ xem/tìm kiếm đảo ngược" trên Bản đồ. Tức 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 , rất tiếc là không được JDK hỗ trợ. Cả Bộ sưu tập chung của Apache và Guava đều cung cấp các triển khai Bản đồ hai chiều được gọi tương ứng là BidiMap và BiMap. Cả hai đều đưa ra một ràng buộc thực thi ánh xạ 1:1 giữa các khóa và giá trị.

7. Bản sao nông của Bản đồ

Hầu như tất cả, nếu không phải tất cả, Bản đồ trong Java đều chứa một hàm tạo bản sao cho một Bản đồ khác. Nhưng quy trình sao chép không được đồng bộ hóa. Điều đó có nghĩa là khi một luồng sao chép Bản đồ, một luồng khác có thể thay đổi cấu trúc của nó. Để ngăn chặn việc đồng bộ hóa bản sao đột ngột, nên sử dụng một trong số chúng trong trường hợp như vậy Collections.synchronizedMap().
Map copiedMap = Collections.synchronizedMap(Map);
Một cách thú vị khác để sao chép nông là sử dụng phần mở rộng clone(). Nhưng nó KHÔNG được khuyến nghị ngay cả bởi người tạo ra khung bộ sưu tập Java, Joshua Bloch. Trong cuộc tranh luận " Copy Constructor vs. Cloning ", anh ấy đảm nhận vị trí: Trích dẫn: "Tôi thường cung cấp một phương thức nhân bản công khai trong các lớp cụ thể vì mọi người mong đợi chúng ở đó. ... thật đáng tiếc khi Nhân bản bị hỏng, nhưng nó đã xảy ra... Nhân bản là một điểm yếu và tôi nghĩ mọi người nên được cảnh báo về những hạn chế của nó." Vì lý do này, tôi thậm chí không chỉ cho bạn cách sử dụng phương pháp sao clone()chép Map

8. Tạo một Bản đồ trống

Nếu Mapkhông thể thay đổi, hãy sử dụng:
Map = Collections.emptyMap();
Hoặc, sử dụng bất kỳ phương án nào khác. Ví dụ:
Map = new HashMap();
KẾT THÚC
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION