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ứcentrySet()
. 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ị.
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:-
Đặ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));
-
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ệnComparable
: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:-
Thứ tự của các phần tử.
HashMap
vàHashtable
khô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,TreeMap
nó đả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. -
Các giá trị hợp lệ.
HashMap
cho phép bạn có một khóa và một giá trị null,HashTable
khô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. -
Đồ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.
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:-
Khởi tạo đối tượng bình thường:
Map<Integer, String> emptyMap = new HashMap<>();
-
Tạo một bản đồ trống bất biến:
Map<Integer, String> emptyMap = Collections.emptyMap();
UnsupportedOperationException
ngoạ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 đồ.
GO TO FULL VERSION