Comment fonctionne la boucle Java «pour chaque»?

1499

Considérer:

List<String> someList = new ArrayList<String>();
// add "monkey", "donkey", "skeleton key" to someList
for (String item : someList) {
    System.out.println(item);
}

À quoi forressemblerait la boucle équivalente sans utiliser la pour chaque syntaxe?

Jay R.
la source
Selon JLS, il a deux formes: stackoverflow.com/a/33232565/1216775
akhil_mittal

Réponses:

1176
for (Iterator<String> i = someIterable.iterator(); i.hasNext();) {
    String item = i.next();
    System.out.println(item);
}

Notez que si vous devez utiliser i.remove();dans votre boucle ou accéder à l'itérateur réel d'une manière ou d'une autre, vous ne pouvez pas utiliser l' for ( : )idiome, car l'itérateur réel est simplement déduit.

Comme l'a noté Denis Bueno, ce code fonctionne pour tout objet qui implémente l' Iterableinterface .

De plus, si le côté droit de l' for (:)idiome est un arrayplutôt qu'un Iterableobjet, le code interne utilise un compteur d'index int et vérifie à la array.lengthplace. Voir la spécification du langage Java .

nsayer
la source
14
J'ai trouvé que d'appeler une boucle while comme while (someList.hasMoreElements ()) {// faire quelque chose}} - me rapproche de la grâce de codage que j'espérais trouver lorsque j'ai cherché cette question.
James T Snell
6
Voir aussi docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html qui explique la boucle foreach (quand elle a été introduite)
PhoneixS
1
pour les développeurs de studio Android: import java.util.Iterator;etimport java.lang.Iterable;
dsdsdsdsd
Frustrant, java.util.Iteratorne met pas en œuvre Iterabledonc vous ne pouvez pas for(String s : (Iterator<String>)foo). Je comprends pourquoi il en est, mais il est irritant.
Christopher Schultz
499

La construction de chacun est également valide pour les tableaux. par exemple

String[] fruits = new String[] { "Orange", "Apple", "Pear", "Strawberry" };

for (String fruit : fruits) {
    // fruit is an element of the `fruits` array.
}

qui est essentiellement équivalent à

for (int i = 0; i < fruits.length; i++) {
    String fruit = fruits[i];
    // fruit is an element of the `fruits` array.
}

Donc, résumé global:
[nsayer] Ce qui suit est la forme la plus longue de ce qui se passe:

for(Iterator<String> i = someList.iterator(); i.hasNext(); ) {
  String item = i.next();
  System.out.println(item);
}

Notez que si vous devez utiliser i.remove (); dans votre boucle, ou accéder à l'itérateur réel d'une manière ou d'une autre, vous ne pouvez pas utiliser l'idiome for (:), car l'itérateur réel est simplement déduit.

[Denis Bueno]

C'est implicite dans la réponse de nsayer, mais il convient de noter que la syntaxe OP pour (..) fonctionnera lorsque "someList" est tout ce qui implémente java.lang.Iterable - il ne doit pas nécessairement s'agir d'une liste ou d'une collection de java.util. Par conséquent, même vos propres types peuvent être utilisés avec cette syntaxe.

Mikezx6r
la source
161

La foreachboucle , ajoutée dans Java 5 (également appelée «boucle améliorée»), équivaut à utiliser java.util.Iteratorle sucre syntaxique d' un --it pour la même chose. Par conséquent, lors de la lecture de chaque élément, un par un et dans l'ordre, unforeach doit toujours être choisi plutôt qu'un itérateur, car il est plus pratique et concis.

pour chaque

for(int i : intList) {
   System.out.println("An element in the list: " + i);
}

Itérateur

Iterator<Integer> intItr = intList.iterator();
while(intItr.hasNext()) {
   System.out.println("An element in the list: " + intItr.next());
}

Il y a des situations où vous devez utiliser un Iteratordirectement. Par exemple, tenter de supprimer un élément tout en utilisant une foreachboîte de conserve (le fera?)ConcurrentModificationException .

foreach contre. for : différences fondamentales

La seule différence pratique entre foret foreachest que, dans le cas d'objets indexables, vous n'avez pas accès à l'index. Un exemple lorsque la forboucle de base est requise:

for(int i = 0; i < array.length; i++) {
   if(i < 5) {
      // Do something special
   }  else {
      // Do other stuff
   }
}

Bien que vous puissiez créer manuellement une variable int d'index distincte avec foreach,

int idx = -1;
for(int i : intArray) {
   idx++;
   ...
}

il n'est pas recommandé, car la portée variable n'est pas idéale et la forboucle de base est simplement le format standard et attendu pour ce cas d'utilisation.

foreachvs for: Performance

Lors de l'accès aux collections, a foreachest beaucoup plus rapide que l' foraccès au tableau de la boucle de base . Cependant, lors de l'accès aux tableaux, au moins avec les tableaux primitifs et wrapper, l'accès via les index est considérablement plus rapide.

Synchronisation de la différence entre l'itérateur et l'accès à l'index pour les tableaux int primitifs

Les index sont 23 à 40 % plus rapides que les itérateurs lors de l'accès intou des Integertableaux. Voici la sortie de la classe testing au bas de cet article, qui résume les nombres dans un tableau primitif-int à 100 éléments (A est un itérateur, B est un index):

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 358,597,622 nanoseconds
Test B: 269,167,681 nanoseconds
B faster by 89,429,941 nanoseconds (24.438799231635727% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 377,461,823 nanoseconds
Test B: 278,694,271 nanoseconds
B faster by 98,767,552 nanoseconds (25.666236154695838% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 288,953,495 nanoseconds
Test B: 207,050,523 nanoseconds
B faster by 81,902,972 nanoseconds (27.844689860906513% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 375,373,765 nanoseconds
Test B: 283,813,875 nanoseconds
B faster by 91,559,890 nanoseconds (23.891659337194227% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 375,790,818 nanoseconds
Test B: 220,770,915 nanoseconds
B faster by 155,019,903 nanoseconds (40.75164734599769% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 326,373,762 nanoseconds
Test B: 202,555,566 nanoseconds
B faster by 123,818,196 nanoseconds (37.437545972215744% faster)

J'ai également exécuté cela pour un Integertableau, et les index sont toujours clairement gagnants, mais seulement entre 18 et 25% plus rapidement.

Pour les collections, les itérateurs sont plus rapides que les index

Pour un Listdes Integerscependant itérateurs sont le grand vainqueur. Modifiez simplement l'int-array dans la classe de test en:

List<Integer> intList = Arrays.asList(new Integer[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100});

Et apportez les modifications nécessaires à la fonction de test ( int[]à List<Integer>, lengthà size(), etc.):

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 3,429,929,976 nanoseconds
Test B: 5,262,782,488 nanoseconds
A faster by 1,832,852,512 nanoseconds (34.326681820485675% faster)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 2,907,391,427 nanoseconds
Test B: 3,957,718,459 nanoseconds
A faster by 1,050,327,032 nanoseconds (26.038700083921256% faster)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 2,566,004,688 nanoseconds
Test B: 4,221,746,521 nanoseconds
A faster by 1,655,741,833 nanoseconds (38.71935684115413% faster)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 2,770,945,276 nanoseconds
Test B: 3,829,077,158 nanoseconds
A faster by 1,058,131,882 nanoseconds (27.134122749113843% faster)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 3,467,474,055 nanoseconds
Test B: 5,183,149,104 nanoseconds
A faster by 1,715,675,049 nanoseconds (32.60101667104192% faster)

[C:\java_code\]java TimeIteratorVsIndexIntList 1000000
Test A: 3,439,983,933 nanoseconds
Test B: 3,509,530,312 nanoseconds
A faster by 69,546,379 nanoseconds (1.4816434912159906% faster)

[C:\java_code\]java TimeIteratorVsIndexIntList 1000000
Test A: 3,451,101,466 nanoseconds
Test B: 5,057,979,210 nanoseconds
A faster by 1,606,877,744 nanoseconds (31.269164666060377% faster)

Dans un test, ils sont presque équivalents, mais avec les collections, l'itérateur gagne.

* Ce message est basé sur deux réponses que j'ai écrites sur Stack Overflow:

Quelques informations supplémentaires: Quelle est la plus efficace, une boucle pour chaque, ou un itérateur?

La classe de test complète

J'ai créé cette classe de comparaison du temps qu'il faut pour faire deux choses après avoir lu cette question sur Stack Overflow:

import  java.text.NumberFormat;
import  java.util.Locale;

/**
   &lt;P&gt;{@code java TimeIteratorVsIndexIntArray 1000000}&lt;/P&gt;

   @see  &lt;CODE&gt;&lt;A HREF=&quot;/programming/180158/how-do-i-time-a-methods-execution-in-java&quot;&gt;/programming/180158/how-do-i-time-a-methods-execution-in-java&lt;/A&gt;&lt;/CODE&gt;
 **/
public class TimeIteratorVsIndexIntArray {

    public static final NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);

    public static final void main(String[] tryCount_inParamIdx0) {
        int testCount;

        // Get try-count from a command-line parameter
        try {
           testCount = Integer.parseInt(tryCount_inParamIdx0[0]);
        }
        catch(ArrayIndexOutOfBoundsException | NumberFormatException x) {
           throw  new IllegalArgumentException("Missing or invalid command line parameter: The number of testCount for each test. " + x);
        }

        //Test proper...START
        int[] intArray = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100};

        long lStart = System.nanoTime();
        for(int i = 0; i < testCount; i++) {
           testIterator(intArray);
        }

        long lADuration = outputGetNanoDuration("A", lStart);

        lStart = System.nanoTime();
        for(int i = 0; i < testCount; i++) {
           testFor(intArray);
        }

        long lBDuration = outputGetNanoDuration("B", lStart);

        outputGetABTestNanoDifference(lADuration, lBDuration, "A", "B");
    }

    private static final void testIterator(int[] int_array) {
       int total = 0;
       for(int i = 0; i < int_array.length; i++) {
          total += int_array[i];
       }
    }

    private static final void testFor(int[] int_array) {
       int total = 0;
       for(int i : int_array) {
          total += i;
       }
    }
    //Test proper...END

    //Timer testing utilities...START
    public static final long outputGetNanoDuration(String s_testName, long l_nanoStart) {
        long lDuration = System.nanoTime() - l_nanoStart;
        System.out.println("Test " + s_testName + ": " + nf.format(lDuration) + " nanoseconds");
        return  lDuration;
    }

    public static final long outputGetABTestNanoDifference(long l_aDuration, long l_bDuration, String s_aTestName, String s_bTestName) {
        long lDiff = -1;
        double dPct = -1.0;
        String sFaster = null;
        if(l_aDuration > l_bDuration) {
            lDiff = l_aDuration - l_bDuration;
            dPct = 100.00 - (l_bDuration * 100.0 / l_aDuration + 0.5);
            sFaster = "B";
        }
        else {
            lDiff = l_bDuration - l_aDuration;
            dPct = 100.00 - (l_aDuration * 100.0 / l_bDuration + 0.5);
            sFaster = "A";
        }
        System.out.println(sFaster + " faster by " + nf.format(lDiff) + " nanoseconds (" + dPct + "% faster)");
        return  lDiff;
   }

   //Timer testing utilities...END

}
aliteralmind
la source
4
Cette réponse est maintenant un article de blog et a été créée à partir de deux réponses connexes que j'ai écrites: ici et ici . Il comprend également une classe génériquement utile pour comparer la vitesse de deux fonctions (en bas).
aliteralmind
1
Juste un petit commentaire ici, vous ne devriez pas déclarer catégoriquement que pour (:) la syntaxe est toujours meilleure pour accéder aux collections; si vous utilisez une liste de tableaux, la boucle for (:) sera environ 2 x plus lente que l'utilisation de for (int i = 0, len = arrayList.size (); i <len; i ++). Je pense que vous l'avez mentionné dans le lien [link] ( stackoverflow.com/questions/2113216/… ) de toute façon, mais il est important de le souligner ...
Leo
@Leo C'est un bon point. Un ArrayList est Collection, mais il est soutenu par un tableau, c'est pourquoi la normale est meilleure pour elle.
aliteralmind
J'imagine que for(int value : int_array) {/* loop content */}c'est le plus lent dans votre test car il est syntaxiquement équivalent à for(int i = 0; i < int_array.length; i++) {int value = int_array[i]; /* loop content */}, ce qui n'est pas ce que votre test compare.
daiscog
(au fait, je ne dis pas que votre test n'est pas valide, mais il peut être utile de noter les raisons de la différence pour que les gens puissent choisir ce qui convient à leur scénario particulier. S'ils font un int value = int_array[i];au début de leur pour boucle, alors ils pourraient aussi bien utiliser foreach. A moins qu'ils n'aient besoin d'accéder à l'index, pour une raison quelconque. En bref, tout dépend du contexte.)
daiscog
129

Voici une réponse qui ne suppose pas la connaissance des Java Iterators. C'est moins précis, mais c'est utile pour l'éducation.

Lors de la programmation, nous écrivons souvent du code qui ressemble à ceci:

char[] grades = ....
for(int i = 0; i < grades.length; i++) {   // for i goes from 0 to grades.length
    System.out.print(grades[i]);           // Print grades[i]
}

La syntaxe foreach permet d'écrire ce modèle commun d'une manière plus naturelle et moins bruyante syntaxiquement.

for(char grade : grades) {   // foreach grade in grades
    System.out.print(grade); // print that grade
}

En outre, cette syntaxe est valide pour les objets tels que les listes ou les ensembles qui ne prennent pas en charge l'indexation de tableau, mais qui implémentent l'interface Java Iterable.

MRocklin
la source
40

La boucle for-each en Java utilise le mécanisme d'itérateur sous-jacent. C'est donc identique à ce qui suit:

Iterator<String> iterator = someList.iterator();

while (iterator.hasNext()) {
  String item = iterator.next();
  System.out.println(item);
}
toluju
la source
25

Dans les fonctionnalités Java 8, vous pouvez utiliser ceci:

List<String> messages = Arrays.asList("First", "Second", "Third");

void forTest(){
    messages.forEach(System.out::println);
}

Production

First
Second
Third
Jrovalle
la source
7
cette information aléatoire ne répond même pas à distance à la question
Tim
25

C'est implicite dans la réponse de nsayer, mais il convient de noter que la syntaxe OP pour (..) fonctionnera lorsque "someList" est tout ce qui implémente java.lang.Iterable - il ne doit pas nécessairement s'agir d'une liste ou d'une collection de java.util. Par conséquent, même vos propres types peuvent être utilisés avec cette syntaxe.

EfForEffort
la source
1
fd est right - le code interne lorsque le côté droit de l'idiome for (:) utilise un int et un array.length au lieu de récupérer un Iterator. forums.sun.com/thread.jspa?messageID=2743233
nsayer
24

Comme défini dans JLS, chaque boucle peut avoir deux formes:

  1. Si le type d'expression est un sous-type, la Iterabletraduction est la suivante:

    List<String> someList = new ArrayList<String>();
    someList.add("Apple");
    someList.add("Ball");
    for (String item : someList) {
        System.out.println(item);
    }
    
    // IS TRANSLATED TO:
    
    for(Iterator<String> stringIterator = someList.iterator(); stringIterator.hasNext(); ) {
        String item = stringIterator.next();
        System.out.println(item);
    }
  2. Si l'expression a nécessairement un type de tableau, T[]alors:

    String[] someArray = new String[2];
    someArray[0] = "Apple";
    someArray[1] = "Ball";
    
    for(String item2 : someArray) {
        System.out.println(item2);
    }
    
    // IS TRANSLATED TO:
    for (int i = 0; i < someArray.length; i++) {
        String item2 = someArray[i];
        System.out.println(item2);
    }

Java 8 a introduit des flux qui fonctionnent généralement mieux. Nous pouvons les utiliser comme:

someList.stream().forEach(System.out::println);
Arrays.stream(someArray).forEach(System.out::println);
akhil_mittal
la source
2
La réponse la plus pertinente et la plus précise. Enchansed a en effet deux traductions.
Zarial
23

Une syntaxe de boucle foreach est:

for (type obj:array) {...}

Exemple:

String[] s = {"Java", "Coffe", "Is", "Cool"};
for (String str:s /*s is the array*/) {
    System.out.println(str);
}

Production:

Java
Coffe
Is
Cool

AVERTISSEMENT: vous pouvez accéder aux éléments du tableau avec la boucle foreach, mais vous ne pouvez PAS les initialiser. Utilisez la forboucle d' origine pour cela.

AVERTISSEMENT: vous devez faire correspondre le type du tableau avec l'autre objet.

for (double b:s) // Invalid-double is not String

Si vous souhaitez modifier des éléments, utilisez la forboucle d' origine comme ceci:

for (int i = 0; i < s.length-1 /*-1 because of the 0 index */; i++) {
    if (i==1) //1 because once again I say the 0 index
        s[i]="2 is cool";
    else
        s[i] = "hello";
}

Maintenant, si nous vidons s sur la console, nous obtenons:

hello
2 is cool
hello
hello
PrivateName
la source
21

La construction de boucle Java "pour chaque" permettra l'itération sur deux types d'objets:

  • T[] (tableaux de tout type)
  • java.lang.Iterable<T>

L' Iterable<T>interface a une seule méthode: Iterator<T> iterator(). Cela fonctionne sur les objets de type Collection<T>car l' Collection<T>interface s'étend Iterable<T>.

Ryan Delucchi
la source
16

Le concept de boucle foreach tel que mentionné dans Wikipedia est mis en évidence ci-dessous:

Contrairement aux autres constructions de boucles for, cependant, les boucles foreach ne conservent généralement pas de compteur explicite : elles disent essentiellement "faire ceci pour tout dans cet ensemble", plutôt que "faire ceci x fois". Cela évite les erreurs potentielles au coup par coup et rend la lecture du code plus simple.

Ainsi, le concept d'une boucle foreach décrit que la boucle n'utilise pas de compteur explicite, ce qui signifie qu'il n'est pas nécessaire d'utiliser des index pour parcourir la liste, ce qui évite à l'utilisateur des erreurs ponctuelles. Pour décrire le concept général de cette erreur off-by-one, prenons un exemple de boucle à parcourir dans une liste à l'aide d'index.

// In this loop it is assumed that the list starts with index 0
for(int i=0; i<list.length; i++){

}

Mais supposons que si la liste commence par l'index 1, cette boucle va lever une exception car elle ne trouvera aucun élément à l'index 0 et cette erreur est appelée une erreur hors-ligne. Donc, pour éviter cette erreur de coup par coup, le concept de boucle foreach est utilisé. Il peut y avoir aussi d'autres avantages, mais c'est ce que je pense être le principal concept et l'avantage d'utiliser une boucle foreach.

oneConsciousness
la source
13

Dans Java 8, ils ont introduit forEach. À l'aide de cette liste, les cartes peuvent être mises en boucle.

Boucler une liste en utilisant pour chacun

List<String> someList = new ArrayList<String>();
someList.add("A");
someList.add("B");
someList.add("C");

someList.forEach(listItem -> System.out.println(listItem))

ou

someList.forEach(listItem-> {
     System.out.println(listItem); 
});

Boucler une carte en utilisant pour chacun

Map<String, String> mapList = new HashMap<>();
    mapList.put("Key1", "Value1");
    mapList.put("Key2", "Value2");
    mapList.put("Key3", "Value3");

mapList.forEach((key,value)->System.out.println("Key: " + key + " Value : " + value));

ou

mapList.forEach((key,value)->{
    System.out.println("Key : " + key + " Value : " + value);
});
vivekkurien
la source
12
for (Iterator<String> itr = someList.iterator(); itr.hasNext(); ) {
   String item = itr.next();
   System.out.println(item);
}
Roger Lindsjö
la source
11

En utilisant des versions Java plus anciennes, Java 7vous pouvez utiliser la foreachboucle comme suit.

List<String> items = new ArrayList<>();
        items.add("A");
        items.add("B");
        items.add("C");
        items.add("D");
        items.add("E");

        for(String item : items){
            System.out.println(item);
        }

Voici la toute dernière façon d'utiliser la foreachboucle dansJava 8

(boucle une liste avec forEach+ expression lambda ou référence de méthode)

//lambda
    //Output : A,B,C,D,E
    items.forEach(item->System.out.println(item));


//method reference
    //Output : A,B,C,D,E
    items.forEach(System.out::println);

Pour plus d'informations, reportez-vous à ce lien.

https://www.mkyong.com/java8/java-8-foreach-examples/

Dulith De Costa
la source
10

Voici une expression équivalente.

for(Iterator<String> sit = someList.iterator(); sit.hasNext(); ) {
    System.out.println(sit.next());
}
Hank
la source
10

Notez également que l'utilisation de la méthode "foreach" dans la question d'origine présente certaines limitations, telles que l'impossibilité de supprimer des éléments de la liste pendant l'itération.

La nouvelle boucle for est plus facile à lire et supprime le besoin d'un itérateur séparé, mais n'est vraiment utilisable que dans les passes d'itération en lecture seule.

billjamesdev
la source
1
Dans ces cas, l'utilisation de removeIfpourrait être le bon outil
ncmathsadist
9

Une alternative à forEach afin d'éviter votre "pour chacun":

List<String> someList = new ArrayList<String>();

Variante 1 (simple):

someList.stream().forEach(listItem -> {
    System.out.println(listItem);
});

Variante 2 (exécution parallèle (plus rapide)):

someList.parallelStream().forEach(listItem -> {
    System.out.println(listItem);
});
Alexander Drobyshevsky
la source
2
Doit mentionner qu'il a été ajouté en Java 1.8
TheLibrarian
Nous ne pouvons pas être sûrs à 100% que le même fil est utilisé. J'aime utiliser le for(formulaire si je veux m'assurer que le même fil est utilisé. J'aime utiliser la forme de flux si j'aime autoriser l'exécution multithread.
Grim
8

Il ajoute de la beauté à votre code en supprimant tout l'encombrement de boucle de base. Il donne un look épuré à votre code, justifié ci-dessous.

forBoucle normale :

void cancelAll(Collection<TimerTask> list) {
    for (Iterator<TimerTask> i = list.iterator(); i.hasNext();)
         i.next().cancel();
}

Utiliser pour chacun:

void cancelAll(Collection<TimerTask> list) {
    for (TimerTask t : list)
        t.cancel();
}

for-each est une construction sur une collection qui implémente Iterator . N'oubliez pas que votre collection doit implémenter Iterator ; sinon vous ne pouvez pas l'utiliser avec for-each.

La ligne suivante se lit comme " pour chaque TimerTask t dans la liste " .

for (TimerTask t : list)

Il y a moins de risques d'erreurs en cas de pour chacun. Vous n'avez pas à vous soucier de l'initialisation de l'itérateur ou de l'initialisation du compteur de boucle et de sa fin (là où il y a possibilité d'erreurs).

Manohar
la source
8

Avant Java 8, vous devez utiliser les éléments suivants:

Iterator<String> iterator = someList.iterator();

while (iterator.hasNext()) {
    String item = iterator.next();
    System.out.println(item);
}

Cependant, avec l'introduction de Streams dans Java 8, vous pouvez faire la même chose avec beaucoup moins de syntaxe. Par exemple, pour votre, someListvous pouvez faire:

someList.stream().forEach(System.out::println);

Vous pouvez en savoir plus sur les flux ici .

stackFan
la source
The foreach loop, added in Java 5 (also called the "enhanced for loop"), is equivalent to using a java.util.Iterator
Alex78191
7

Cela ressemblerait à quelque chose comme ça. Très cruel.

for (Iterator<String> i = someList.iterator(); i.hasNext(); )
        System.out.println(i.next());

Il y a un bon writeup sur chaque dans la documentation Sun .

Pete
la source
6

Comme l'ont dit tant de bonnes réponses, un objet doit implémenter le Iterable interfaces'il veut utiliser une for-eachboucle.

Je vais publier un exemple simple et essayer d'expliquer d'une manière différente le fonctionnement d'une for-eachboucle.

L' for-eachexemple de boucle:

public class ForEachTest {

    public static void main(String[] args) {

        List<String> list = new ArrayList<String>();
        list.add("111");
        list.add("222");

        for (String str : list) {
            System.out.println(str);
        }
    }
}

Ensuite, si nous utilisons javappour décompiler cette classe, nous obtiendrons cet exemple de bytecode:

public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=4, args_size=1
         0: new           #16                 // class java/util/ArrayList
         3: dup
         4: invokespecial #18                 // Method java/util/ArrayList."<init>":()V
         7: astore_1
         8: aload_1
         9: ldc           #19                 // String 111
        11: invokeinterface #21,  2           // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        16: pop
        17: aload_1
        18: ldc           #27                 // String 222
        20: invokeinterface #21,  2           // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        25: pop
        26: aload_1
        27: invokeinterface #29,  1           // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;

Comme nous pouvons le voir sur la dernière ligne de l'exemple, le compilateur convertira automatiquement l'utilisation de for-eachmot - clé en utilisation Iteratorau moment de la compilation. Cela peut expliquer pourquoi l'objet, qui n'implémente pas le Iterable interface, lancera un Exceptionlorsqu'il essaie d'utiliser la for-eachboucle.

L Joey
la source
6

Le Java pour chaque boucle (alias amélioré pour la boucle) est une version simplifiée d'une boucle pour. L'avantage est qu'il y a moins de code à écrire et moins de variables à gérer. L'inconvénient est que vous n'avez aucun contrôle sur la valeur de l'étape et aucun accès à l'index de boucle à l'intérieur du corps de boucle.

Il est préférable de les utiliser lorsque la valeur de l'étape est un simple incrément de 1 et lorsque vous avez uniquement besoin d'accéder à l'élément de boucle actuel. Par exemple, si vous devez parcourir tous les éléments d'un tableau ou d'une collection sans jeter un œil devant ou derrière l'élément actuel.

Il n'y a pas d'initialisation de boucle, pas de condition booléenne et la valeur de l'étape est implicite et est un simple incrément. C'est pourquoi ils sont considérés comme beaucoup plus simples que réguliers pour les boucles.

Amélioré pour les boucles suivent cet ordre d'exécution:

1) corps de boucle

2) répéter à partir de l'étape 1 jusqu'à ce que l'ensemble du tableau ou de la collection ait été traversé

Exemple - tableau entier

int [] intArray = {1, 3, 5, 7, 9};
for(int currentValue : intArray) {
  System.out.println(currentValue);
}

La variable currentValue contient la valeur actuelle en boucle dans le tableau intArray. Notez qu'il n'y a pas de valeur de pas explicite - c'est toujours un incrément de 1.

On peut penser que le côlon signifie «dedans». Ainsi, la déclaration de la boucle for améliorée indique: boucle sur intArray et stocke la valeur int du tableau actuel dans la variable currentValue.

Production:

1
3
5
7
9

Exemple - String Array

Nous pouvons utiliser la boucle for-each pour parcourir un tableau de chaînes. La déclaration de boucle indique: boucle sur le tableau de chaînes myStrings et stocke la valeur de chaîne actuelle dans la variable currentString.

String [] myStrings  = {
  "alpha",
  "beta",
  "gamma",
  "delta"
};

for(String currentString : myStrings) {
  System.out.println(currentString);
}

Production:

alpha
beta
gamma
delta

Exemple - Liste

La boucle for améliorée peut également être utilisée pour parcourir un java.util.List comme suit:

List<String> myList = new ArrayList<String>();
myList.add("alpha");
myList.add("beta");
myList.add("gamma");
myList.add("delta");

for(String currentItem : myList) {
  System.out.println(currentItem);
}

La déclaration de boucle indique: boucle sur myList List of Strings et stocke la valeur List actuelle dans la variable currentItem.

Production:

alpha
beta
gamma
delta

Exemple - Définir

La boucle for améliorée peut également être utilisée pour itérer sur un java.util.Set comme suit:

Set<String> mySet = new HashSet<String>();
mySet.add("alpha");
mySet.add("alpha");
mySet.add("beta");
mySet.add("gamma");
mySet.add("gamma");
mySet.add("delta");

for(String currentItem : mySet) {
  System.out.println(currentItem);
}

La déclaration de boucle indique: boucle sur mySet Set of Strings et stocke la valeur Set actuelle dans la variable currentItem. Notez que puisqu'il s'agit d'un ensemble, les valeurs de chaîne en double ne sont pas stockées.

Production:

alpha
delta
beta
gamma

Source: boucles en Java - Ultimate Guide

gomisha
la source
4
public static Boolean Add_Tag(int totalsize)
{ List<String> fullst = new ArrayList<String>();
            for(int k=0;k<totalsize;k++)
            {
              fullst.addAll();
            }
}
Santhosh Rajkumar
la source
3

L'idiome Java for-each ne peut être appliqué qu'aux tableaux ou aux objets de type * Iterable . Cet idiome est implicite car il est vraiment soutenu par un itérateur. L'itérateur est programmé par le programmeur et utilise souvent un index entier ou un nœud (selon la structure des données) pour garder une trace de sa position. Sur le papier, il est plus lent qu'une boucle for régulière, du moins pour les structures "linéaires" comme les tableaux et les listes, mais il fournit une plus grande abstraction.

TheArchon
la source
-1: c'est beaucoup moins lisible (généralement): même votre propre exemple (le premier) est faux, car il laisse de côté le premier élément du tableau.
Ondrej Skopek
2

Ça a l'air fou mais bon ça marche

List<String> someList = new ArrayList<>(); //has content
someList.forEach(System.out::println);

Cela marche. la magie

Rei Brown
la source
1
Cela nécessite Java 1.8 +
BARNI
2
ne répond même pas à distance à la question
Tim
2

Comme beaucoup d'autres réponses le disent correctement, le for each loopsucre est simplement syntaxique sur le même ancien for loopet le compilateur le traduit dans le même ancien pour la boucle.

javac (open jdk) a un commutateur -XD-printflat, qui génère un fichier java avec tout le sucre syntaxique supprimé. la commande complète ressemble à ceci

javac -XD-printflat -d src/ MyFile.java

//-d is used to specify the directory for output java file

Permet donc de retirer le sucre syntaxique

Pour répondre à cette question, j'ai créé un fichier et écrit deux versions de for each, une avec arrayet une autre avec a list. mon javadossier ressemblait à ceci.

import java.util.*;
public class Temp{

    private static void forEachArray(){
        int[] arr = new int[]{1,2,3,4,5};
        for(int i: arr){
            System.out.print(i);
        }
    }

    private static void forEachList(){
        List<Integer> list = Arrays.asList(1,2,3,4,5);
        for(Integer i: list){
            System.out.print(i);
        }
    }
}

Lorsque j'ai compiledce fichier avec le commutateur ci-dessus, j'ai obtenu la sortie suivante.

import java.util.*;

public class Temp {

    public Temp() {
        super();
    }

    private static void forEachArray() {
        int[] arr = new int[]{1, 2, 3, 4, 5};
        for (/*synthetic*/ int[] arr$ = arr, len$ = arr$.length, i$ = 0; i$ < len$; ++i$) {
            int i = arr$[i$];
            {
                System.out.print(i);
            }
        }
    }

    private static void forEachList() {
        List list = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3), Integer.valueOf(4), Integer.valueOf(5)});
        for (/*synthetic*/ Iterator i$ = list.iterator(); i$.hasNext(); ) {
            Integer i = (Integer)i$.next();
            {
                System.out.print(i);
            }
        }
    }
}

Vous pouvez voir que, avec l'autre sucre syntaxique (Autoboxing), chaque boucle a été remplacée par une boucle simple.

mightyWOZ
la source
-2
List<Item> Items = obj.getItems();
for(Item item:Items)
             {
                System.out.println(item); 
             }

Itère tous les objets de la table Items.

shubhranshu
la source
1
L'utilisateur n'a pas demandé la syntaxe
pradipgarala