Java: il modo migliore per scorrere una raccolta (qui ArrayList)

Oggi stavo codificando felicemente quando sono arrivato a un pezzo di codice che ho già usato centinaia di volte:

Iterazione attraverso una raccolta (qui ArrayList)

per qualche motivo, ho effettivamente esaminato le opzioni di completamento automatico di Eclipse e mi sono chiesto:

Quali casi sono i cicli seguenti migliori da usare rispetto agli altri?

Il classico ciclo di indice di array:

for (int i = 0; i < collection.length; i++) { type array_element = collection.get(index); } 

The Iterator hasNext () / next ():

 for (Iterator iterator = collection.iterator(); iterator.hasNext();) { type type = (type) iterator.next(); } 

E il mio preferito perché è così semplice da scrivere:

 for (iterable_type iterable_element : collection) { } 

Il primo è utile quando è necessario anche l’indice dell’elemento. Questo è fondamentalmente equivalente alle altre due varianti per ArrayList , ma sarà molto lento se si utilizza una LinkedList .

Il secondo è utile quando non è necessario l’indice dell’elemento, ma potrebbe essere necessario rimuovere gli elementi durante l’iterazione. Ma questo ha lo svantaggio di essere un po ‘troppo verboso IMO.

Anche la terza versione è la mia scelta preferita. È breve e funziona per tutti i casi in cui non è necessario alcun indice o l’iteratore sottostante (ovvero si sta solo accedendo agli elementi, non rimuovendoli o modificando la Collection in alcun modo – che è il caso più comune).

Tutti loro hanno i propri usi:

  1. Se hai un iterabile e devi attraversare incondizionatamente a tutti loro:

    for (iterable_type iterable_element: collection)

  2. Se hai un iterabile ma devi attraversare condizionatamente:

    for (Iterator iterator = collection.iterator (); iterator.hasNext ();)

  3. Se la struttura dati non implementa iterabile:

    for (int i = 0; i

C’è anche l’utilità stream () delle raccolte con Java 8

 collection.forEach((temp) -> { System.out.println(temp); }); 

o

 collection.forEach(System.out::println); 

Maggiori informazioni su Java 8 stream e raccolte per il link dei prodigiosi

Nessuno di loro è “migliore” degli altri. Il terzo è, per me, più leggibile, ma per qualcuno che non usa la foreach potrebbe sembrare strano (potrebbero preferire il primo). Tutti e 3 sono abbastanza chiari a chiunque comprenda Java, quindi scegli quello che ti fa sentire meglio riguardo al codice.

Il primo è il più basilare, quindi è il modello più universale (funziona per gli array, tutti i iterabili a cui riesco a pensare). Questa è l’unica differenza che riesco a pensare. In casi più complicati (es. È necessario avere accesso all’indice corrente, o è necessario filtrare l’elenco), il primo e il secondo caso potrebbero avere più senso, rispettivamente. Per il caso semplice (object iterabile, nessun requisito speciale), il terzo sembra il più pulito.

La prima opzione è una migliore performance wise (come ArrayList implementa l’interfaccia RandomAccess). Come per il java doc, un’implementazione List dovrebbe implementare l’interfaccia RandomAccess se, per le tipiche istanze della class, questo ciclo:

  for (int i=0, n=list.size(); i < n; i++) list.get(i); 

corre più veloce di questo ciclo:

  for (Iterator i=list.iterator(); i.hasNext(); ) i.next(); 

Spero possa essere d'aiuto. La prima opzione sarebbe lenta per gli elenchi di accesso sequenziali.

Ecco un esempio

 Query query = em.createQuery("from Student"); java.util.List list = query.getResultList(); for (int i = 0; i < list.size(); i++) { student = (Student) list.get(i); System.out.println(student.id + " " + student.age + " " + student.name + " " + student.prenom); }