Будучи дещо новим у мові Java, я намагаюся ознайомитись із усіма способами (або принаймні непатологічними), які можна переглядати за допомогою списку (чи, можливо, інших колекцій) та з перевагами чи недоліками кожного.
З огляду на List<E> list
об'єкт, я знаю наступні способи провести цикл крізь усі елементи:
Основні для циклу (звичайно, є і еквівалентні while
/ do while
цикли)
// 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
// ...
}
Примітка. Як зазначав @amarseillan, ця форма є поганим вибором для повторення часу List
, оскільки реальна реалізація get
методу може бути не такою ефективною, як при використанні Iterator
. Наприклад, LinkedList
реалізації повинні пройти всі елементи, що передують i, щоб отримати i-й елемент.
У наведеному вище прикладі немає способу List
реалізації "зберегти своє місце", щоб зробити майбутні ітерації більш ефективними. Для цього ArrayList
це насправді не має значення, оскільки складність / вартість get
постійного часу (O (1)), тоді як для a LinkedList
пропорційна величині списку (O (n)).
Щоб отримати докладнішу інформацію про складність обчислювальної техніки вбудованих Collections
реалізацій, перегляньте це питання .
Покращений цикл (добре пояснено в цьому запитанні )
for (E element : list) {
// 1 - can call methods of element
// ...
}
Ітератор
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
// ...
}
Функціональна Java
list.stream().map(e -> e + 1); // Can apply a transformation function for e
Iterable.forEach , Stream.forEach , ...
(Метод карти з потокового API Java 8 (див. Відповідь @ i_am_zero).)
У класах колекції Java 8, які реалізують Iterable
(наприклад, всі List
s), тепер є forEach
метод, який можна використовувати замість викладеного вище оператора циклу . (Ось ще одне питання, яке забезпечує хороше порівняння.)
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).
Які ще способи існують, якщо такі є?
(До речі, мій інтерес зовсім не випливає з бажання оптимізувати продуктивність ; я просто хочу знати, які форми доступні мені як розробнику.)
List
інтерфейсу конкретно?