Là một phần mới đối với ngôn ngữ Java Tôi đang cố gắng làm quen với tất cả các cách (hoặc ít nhất là những cách không bệnh lý) mà người ta có thể lặp lại qua một danh sách (hoặc có lẽ các bộ sưu tập khác) và những ưu điểm hoặc nhược điểm của mỗi cách.
Đưa ra một List<E> list
đối tượng, tôi biết các cách sau để lặp qua tất cả các yếu tố:
Cơ bản cho vòng lặp (tất nhiên, cũng có tương đương while
/ do while
vòng lặp)
// Not recommended (see below)!
for (int i = 0; i < list.size(); i++) {
E element = list.get(i);
// 1 - can call methods of element
// 2 - can use 'i' to make index-based calls to methods of list
// ...
}
Lưu ý: Như @amarseillan đã chỉ ra, hình thức này là một lựa chọn kém cho việc lặp lại qua List
s, bởi vì việc triển khai thực tế của get
phương pháp có thể không hiệu quả như khi sử dụng Iterator
. Ví dụ, LinkedList
việc triển khai phải duyệt qua tất cả các phần tử trước i để có phần tử thứ i.
Trong ví dụ trên, không có cách nào để List
triển khai "lưu vị trí của nó" để làm cho các lần lặp lại trong tương lai hiệu quả hơn. Đối với một ArrayList
điều đó không thực sự quan trọng, bởi vì độ phức tạp / chi phí get
là thời gian không đổi (O (1)) trong khi đối với a LinkedList
là tỷ lệ với kích thước của danh sách (O (n)).
Để biết thêm thông tin về độ phức tạp tính toán của các Collections
triển khai tích hợp, hãy xem câu hỏi này .
Tăng cường cho vòng lặp (giải thích độc đáo trong câu hỏi này )
for (E element : list) {
// 1 - can call methods of element
// ...
}
Lặp lại
for (Iterator<E> iter = list.iterator(); iter.hasNext(); ) {
E element = iter.next();
// 1 - can call methods of element
// 2 - can use iter.remove() to remove the current element from the list
// ...
}
ListIterator
for (ListIterator<E> iter = list.listIterator(); iter.hasNext(); ) {
E element = iter.next();
// 1 - can call methods of element
// 2 - can use iter.remove() to remove the current element from the list
// 3 - can use iter.add(...) to insert a new element into the list
// between element and iter->next()
// 4 - can use iter.set(...) to replace the current element
// ...
}
Chức năng Java
list.stream().map(e -> e + 1); // Can apply a transformation function for e
Iterable.forEach , Stream.forEach , ...
(Một phương pháp bản đồ từ API Stream của Java 8 (xem câu trả lời @ i_am_zero).)
Trong các lớp tập hợp Java 8 triển khai Iterable
(ví dụ, tất cả các List
s) hiện có một forEach
phương thức, có thể được sử dụng thay cho câu lệnh for loop được trình bày ở trên. (Đây là một câu hỏi khác cung cấp một so sánh tốt.)
Arrays.asList(1,2,3,4).forEach(System.out::println);
// 1 - can call methods of an element
// 2 - would need reference to containing object to remove an item
// (TODO: someone please confirm / deny this)
// 3 - functionally separates iteration from the action
// being performed with each item.
Arrays.asList(1,2,3,4).stream().forEach(System.out::println);
// Same capabilities as above plus potentially greater
// utilization of parallelism
// (caution: consequently, order of execution is not guaranteed,
// see [Stream.forEachOrdered][stream-foreach-ordered] for more
// information about this).
Những cách khác là có, nếu có?
(BTW, mối quan tâm của tôi hoàn toàn không xuất phát từ mong muốn tối ưu hóa hiệu suất ; tôi chỉ muốn biết những hình thức nào có sẵn cho tôi với tư cách là nhà phát triển.)
List
giao diện cụ thể?