Essendo un po 'nuovo nel linguaggio Java, sto cercando di familiarizzare con tutti i modi (o almeno quelli non patologici) che uno potrebbe scorrere attraverso un elenco (o forse altre raccolte) e i vantaggi o gli svantaggi di ciascuno.
Dato un List<E> list
oggetto, conosco i seguenti modi per scorrere tutti gli elementi:
Basic per loop (ovviamente, ci sono anche equivalenti while
/ do while
loop)
// 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
// ...
}
Nota: Come sottolineato da @amarseillan, questo modulo è una scelta sbagliata per iterare su List
s, poiché l'implementazione effettiva del get
metodo potrebbe non essere efficiente come quando si usa un Iterator
. Ad esempio, le LinkedList
implementazioni devono attraversare tutti gli elementi che precedono i per ottenere l'i-esimo elemento.
Nell'esempio sopra non è possibile che l' List
implementazione "salvi il suo posto" per rendere le iterazioni future più efficienti. Per un ArrayList
non importa, perché la complessità / costo di get
è tempo costante (O (1)) mentre per a LinkedList
è proporzionale alla dimensione della lista (O (n)).
Per ulteriori informazioni sulla complessità computazionale delle Collections
implementazioni integrate , consulta questa domanda .
Migliorato per il ciclo (ben spiegato in questa domanda )
for (E element : list) {
// 1 - can call methods of element
// ...
}
Iterator
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 funzionale
list.stream().map(e -> e + 1); // Can apply a transformation function for e
Iterable.forEach , Stream.forEach , ...
(Un metodo cartografico dall'API Stream di Java 8 (vedi la risposta di @ i_am_zero).)
In Java 8 le classi di raccolta che implementano Iterable
(per esempio, tutte le List
s) ora hanno un forEach
metodo, che può essere usato al posto dell'istruzione for loop mostrata sopra. (Ecco un'altra domanda che fornisce un buon confronto.)
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).
Quali altri modi ci sono, se ce ne sono?
(A proposito, il mio interesse non deriva affatto dal desiderio di ottimizzare le prestazioni ; voglio solo sapere quali moduli sono disponibili per me come sviluppatore.)
List
sull'interfaccia è specifica?