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> listoggetto, conosco i seguenti modi per scorrere tutti gli elementi:
Basic per loop (ovviamente, ci sono anche equivalenti while/ do whileloop)
// 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 Lists, poiché l'implementazione effettiva del getmetodo potrebbe non essere efficiente come quando si usa un Iterator. Ad esempio, le LinkedListimplementazioni devono attraversare tutti gli elementi che precedono i per ottenere l'i-esimo elemento.
Nell'esempio sopra non è possibile che l' Listimplementazione "salvi il suo posto" per rendere le iterazioni future più efficienti. Per un ArrayListnon 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 Collectionsimplementazioni 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 Lists) ora hanno un forEachmetodo, 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.)
Listsull'interfaccia è specifica?