2011-03-15 4 views
3

J'ai des difficultés à comprendre une boucle pour chaque boucle. Je suis familier avec la structure typique d'un pour-chacun, où il y a construit dans le compteur et la déclaration d'affectation à chaque élément. Cependant, dans le code ci-dessous, que signifie le "nouveau" mot-clé? Est-ce qu'il s'exécute seulement une fois?Pour chaque boucle Question

for(Integer item : new ArrayList<Integer>(myCollection)){ 
    myCollection.add(first.intValue() + item.intValue()); 
} 

Est-ce équivalent à la boucle suivante?

for(int ctr = 0; ctr < myCollection.size(); ctr++){ 
    Integer temp = myCollection.get(ctr); 
    myCollection.add(first.intValue() + item.intValue()); 
} 
+0

Je suppose que vous vouliez un first.intValue() au lieu de first, intValue() –

+0

Est-ce que personne n'a mentionné O (n^2) pour un 'LinkedList <> myCollection'? –

Répondre

4

Le mot clé new implique qu'il créera une nouvelle ArrayList, comme si elle se trouvait ailleurs dans le code.

Le code est fondamentalement le même que celui qui suit. L'utilisation de new dans une boucle for-each n'a rien de spécial. Ce n'est pas la même chose que votre boucle alternative car la taille() change lorsque vous y ajoutez des choses. Je suppose que vous avez l'intention pour ctr et i être les mêmes. Il est équivalent à

for(int i = 0, size = myCollection.size(); i < size; i++){ 
    myCollection.add(first.intValue() + myCollection.get(i).intValue()); 
} 

que j'imagine est le même que

for(int i = 0, size = myCollection.size(); i < size; i++) 
    myCollection.add(first + myCollection.get(i)); 
+1

merci pour la réponse détaillée! beaucoup aidé! – maru

2

Le premier bloc de code crée une nouvelle ArrayList de Integers, copie le contenu de myCollection dans, puis itère sur la ArrayList résultant.

La copie est nécessaire car l'original myCollection est modifié dans la boucle.

Le deuxième bloc de code n'est pas équivalent au premier car il ajoute des éléments à myCollection lors de son itération. En raison de cette interaction, il ne fera pas ce que vous attendez et se traduira par une boucle infinie.

+0

Étant pédant, plutôt que d'entrer dans une boucle infinie, une ArrayList ne peut avoir que 2^31-1 éléments. En fait, il s'arrêtera à environ 1,4 milliard alors qu'il essaye de croître à plus d'un certain nombre d'éléments à ce moment-là. ;) Si vous utilisiez une LinkedList, elle s'arrêterait à Integer.MAX_VALUE car c'est la taille maximale() qui peut retourner. –

0

Les deux codes que vous fournissez sont très similaires, mais la différence principale (il y a mot-clé new) est que dans le premier code que vous créez copie de la liste d'origine. Ceci est nécessaire car dans la boucle, vous ajoutez plus d'éléments à la liste, augmentant ainsi sa taille. De cette façon, la boucle ne sortira jamais et vous finirez par avoir de la mémoire.

Le code équivalent en utilisant for(;;) serait la suivante:

List<Integer> auxList = new ArrayList<Integer>(myCollection); 
for(int ctr = 0; ctr < auxList.size(); ctr++){ 
    myCollection.add(first.intValue() + auxList.get(ctr)); 
} 

vous pourriez aussi simplement précalculer la taille pour éviter ce captcha:

int size = myCollection.size(); 
for(int ctr = 0; ctr < size; ctr++){ 
    myCollection.add(first.intValue() + myCollection.get(ctr)); 
} 

Autre que cela, la seule différence est que la L'approche foreach utilise des itérateurs au lieu d'accéder aux éléments par des index.

J'espère que ça aide!

0

Est-ce qu'il s'exécute une seule fois?

Oui.

Est-ce équivalent à ce qui suit pour la boucle?

Non Votre boucle qui suit

  1. a trois erreurs (first,intValue(), l'indice de boucle est ctr mais myCollection.get(i), vous allez chercher dans temp et laissez item non défini),
  2. itère sur myCollection, ajoutant il, tout en continuellement vérifier contre une taille croissante, et donc
  3. ne se termine pas (size() est de plus en plus), sauf qu'il
  4. finira par lancer un .

Il est, cependant, ce qui équivaut à ce

for (int i = 0, n = myCollections.size(); i < n; i++) { 
    Integer item = myCollection.get(i); 
    myCollection.add(first.intValue() + item.intValue()); 
} 
0

Votre boucle

for(Integer item : new ArrayList<Integer>(myCollection)){ 
    myCollection.add(first.intValue() + item.intValue()); 
} 

est compilé au même code (modulo noms de variables) comme

for (Iterator<Integer> iterator = new ArrayList<Integer>(myCollection).iterator(); 
    it.hasNext();) { 
    Integer item = iterator.next(); 
    myCollection.add(first.intValue() + item.intValue()); 
} 

Si la taille de myCollection ne change pas (et myCollecti sur est un List), alors ce serait la même chose (seulement moins efficace pour la création d'une liste temporaire) comme

for(int ctr = 0; ctr < myCollection.size(); ctr++){ 
    Integer temp = myCollection.get(i); 
    myCollection.add(first.intValue() + temp.intValue()); 
} 

... mais vous changez myCollection dans la boucle, cette deuxième boucle ne jamais atteindre le fin (en supposant qu'il y ait au moins un élément).

Ainsi, votre ArrayList aide votre boucle à bien se comporter.