Như đã trình bày trong các câu trả lời, về cơ bản có hai cách để lặp qua một Map
(hãy giả sử Map<String, String>
trong những ví dụ).
lặp trên Map#entrySet()
:
for (Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
lặp trên Map#keySet()
và sau đó sử dụng Map#get()
để có được giá trị cho tất cả các chìa khóa:
for (String key : map.keySet()) {
System.out.println(key + "=" + map.get(key));
}
Điều thứ hai là có thể nhiều hơn có thể đọc được, nhưng nó có chi phí hiệu suất của việc gọi không cần thiết get()
trên mọi lần lặp lại. Người ta có thể lập luận rằng việc tạo trình vòng lặp keyset ít tốn kém hơn vì nó không cần tính đến các giá trị. Nhưng hãy tin hay không, số keySet().iterator()
sẽ tạo và sử dụng cùng một lần lặp làm entrySet().iterator()
. Sự khác biệt duy nhất là trong trường hợp của keySet()
, cuộc gọi next()
của trình vòng lặp trả về it.next().getKey()
thay vì it.next()
.
Các AbstractMap#keySet()
's javadoc chứng minh điều này:
phương pháp lặp của lớp con trả về một "đối tượng wrapper" trên entrySet()
iterator của bản đồ này.
Mã nguồn AbstractMap
cũng chứng minh điều này. Dưới đây là một trích keySet()
phương pháp (ở đâu đó xung quanh dòng 300 trong Java 1.6):
public Iterator<K> iterator() {
return new Iterator<K>() {
private Iterator<Entry<K,V>> i = entrySet().iterator(); // <-----
public boolean hasNext() {
return i.hasNext();
}
public K next() {
return i.next().getKey(); // <-----
}
public void remove() {
i.remove();
}
};
}
Lưu ý rằng khả năng đọc nên được ưa thích hơn tối ưu hóa quá sớm, nhưng điều quan trọng là phải có này trong tâm trí.
So sánh điều này với phiên bản Python nhắc tôi tại sao tôi đã từ bỏ Java năm trước. –