Étant un peu nouveau dans le langage Java, j'essaie de me familiariser avec toutes les façons (ou au moins celles non pathologiques) que l'on pourrait parcourir à travers une liste (ou peut-être d'autres collections) et les avantages ou les inconvénients de chacun.
Étant donné un List<E> listobjet, je connais les façons suivantes de parcourir tous les éléments:
De base pour la boucle (bien sûr, il existe également des boucles while/ équivalentes 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
// ...
}
Remarque: Comme @amarseillan l'a souligné, ce formulaire est un mauvais choix pour itérer sur Lists, car l'implémentation réelle de la getméthode peut ne pas être aussi efficace que lors de l'utilisation d'un Iterator. Par exemple, les LinkedListimplémentations doivent traverser tous les éléments précédant i pour obtenir le i-ème élément.
Dans l'exemple ci-dessus, l' Listimplémentation n'a aucun moyen de "sauver sa place" pour rendre les futures itérations plus efficaces. Pour un, ArrayListcela n'a pas vraiment d'importance, car la complexité / le coût de getest un temps constant (O (1)) tandis que pour un LinkedListil est proportionnel à la taille de la liste (O (n)).
Pour plus d'informations sur la complexité de calcul des Collectionsimplémentations intégrées , consultez cette question .
Amélioré pour la boucle (bien expliqué dans cette question )
for (E element : list) {
// 1 - can call methods of element
// ...
}
Itérateur
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 fonctionnel
list.stream().map(e -> e + 1); // Can apply a transformation function for e
Iterable.forEach , Stream.forEach , ...
(Une méthode de carte de l'API Stream de Java 8 (voir la réponse de @ i_am_zero).)
Dans Java 8, les classes de collection qui implémentent Iterable(par exemple, tous les Lists) ont désormais une forEachméthode, qui peut être utilisée à la place de l' instruction for loop illustrée ci-dessus. (Voici une autre question qui fournit une bonne comparaison.)
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).
Quels autres moyens existe-t-il, le cas échéant?
(BTW, mon intérêt ne découle pas du tout d'un désir d' optimiser les performances ; je veux juste savoir quelles formes sont à ma disposition en tant que développeur.)
Listinterface est-elle spécifique?