Como funciona o loop Java 'para cada'?

1499

Considerar:

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

Como seria o forloop equivalente sem usar o para cada sintaxe?

Jay R.
fonte
De acordo com o JLS, ele tem duas formas: stackoverflow.com/a/33232565/1216775
akhil_mittal

Respostas:

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

Observe que se você precisar usar i.remove();em seu loop ou acessar o iterador real de alguma maneira, não poderá usar o for ( : )idioma, pois o iterador real é apenas inferido.

Como observado por Denis Bueno, esse código funciona para qualquer objeto que implemente a Iterableinterface .

Além disso, se o lado direito do for (:)idioma for arrayum Iterableobjeto, e não um objeto, o código interno usará um contador de índice int e fará uma verificação array.length. Veja a especificação da linguagem Java .

nsayer
fonte
14
Descobri que apenas chamar um loop while como while (someList.hasMoreElements ()) {// do something}} - me aproxima da graça da codificação que eu esperava encontrar ao pesquisar essa pergunta.
James T Snell
6
Ver também docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html que explicam o loop foreach (quando foi introduzido)
PhoneixS
1
para desenvolvedores estúdio Android: import java.util.Iterator;eimport java.lang.Iterable;
dsdsdsdsd
Frustrantemente, java.util.Iteratornão implementa, Iterableentão você não pode for(String s : (Iterator<String>)foo). Eu entendo por que isso é, mas é irritante.
Christopher Schultz
499

A construção de cada um também é válida para matrizes. por exemplo

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

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

que é essencialmente equivalente a

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

Portanto, resumo geral:
[nsayer] A seguir, é a forma mais longa do que está acontecendo:

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

Observe que se você precisar usar i.remove (); em seu loop ou acessar o iterador real de alguma forma, você não pode usar o idioma for (:), pois o iterador real é apenas inferido.

Denis Bueno

Está implícito na resposta do nsayer, mas vale a pena notar que os OP para a sintaxe (..) funcionarão quando "someList" for qualquer coisa que implemente java.lang.Iterable - ele não precisa ser uma lista ou uma coleção de java.util. Mesmo seus próprios tipos, portanto, podem ser usados ​​com essa sintaxe.

Mikezx6r
fonte
161

O foreachloop , adicionado no Java 5 (também chamado de "loop for aprimorado"), é equivalente a usar java.util.Iteratoro açúcar sintático de a - para a mesma coisa. Portanto, ao ler cada elemento, um por um e em ordem, a foreachsempre deve ser escolhido sobre um iterador, pois é mais conveniente e conciso.

para cada

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

Iterador

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

Há situações em que você deve usar um Iteratordiretamente. Por exemplo, tentar excluir um elemento enquanto estiver usando uma foreachlata (resultará em?) Resultará em a ConcurrentModificationException.

foreachvs for.: diferenças básicas

A única diferença prática entre fore foreaché que, no caso de objetos indexáveis, você não tem acesso ao índice. Um exemplo quando o forloop básico é necessário:

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

Embora você possa criar manualmente uma variável int de índice separada com foreach,

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

não é recomendado, pois o escopo da variável não é o ideal e o forloop básico é simplesmente o formato padrão e esperado para este caso de uso.

foreachvs for.: Desempenho

Ao acessar coleções, a foreaché significativamente mais rápido que o foracesso à matriz do loop básico . Ao acessar matrizes, no entanto - pelo menos com matrizes primitivas e wrapper -, o acesso via índices é muito mais rápido.

Cronometrando a diferença entre o acesso do iterador e do índice para matrizes int primitivas

Os índices são 23 a 40 % mais rápidos que os iteradores ao acessar intou Integermatrizes. Aqui está o resultado da classe de teste na parte inferior deste post, que soma os números em uma matriz primitiva-int de 100 elementos (A é o iterador, B é o índice):

[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)

Também executei isso para uma Integermatriz e os índices ainda são os vencedores, mas apenas entre 18 e 25% mais rápidos.

Para coleções, os iteradores são mais rápidos que os índices

Para um Listdos Integers, no entanto, os iteradores são o vencedor claro. Apenas altere a matriz int na classe de teste para:

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});

E faça as alterações necessárias na função de teste ( int[]para List<Integer>, lengthpara 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)

Em um teste, eles são quase equivalentes, mas com coleções, o iterador vence.

* Este post é baseado em duas respostas que escrevi no Stack Overflow:

Mais algumas informações: Qual é mais eficiente, um loop para cada ou um iterador?

A classe de teste completa

Eu criei essa classe comparar o tempo necessário para fazer duas coisas depois de ler esta pergunta no 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
fonte
4
Esta resposta agora é uma postagem de blog e foi criada a partir de duas respostas relacionadas que eu escrevi: aqui e aqui . Ele também inclui uma classe genericamente útil para comparar a velocidade de duas funções (na parte inferior).
Alreralmind
1
Apenas um pequeno comentário aqui, você não deve declarar categoricamente que a sintaxe para (:) é sempre melhor para acessar coleções; se você estiver usando uma lista de matrizes, o loop for (:) será cerca de 2 x mais lento que o for (int i = 0, len = arrayList.size (); i <len; i ++). Eu acho que você mencionou que no [link] ( stackoverflow.com/questions/2113216/... link) de qualquer maneira, mas é importante ressaltar que ...
Leo
@ Leo É um bom ponto. Um ArrayList é Collection, mas é apoiado por um array, e é por isso que o normal para é melhor para ele.
precisa saber é o seguinte
Eu imagino que o for(int value : int_array) {/* loop content */}é o mais lento no seu teste, porque é sintaticamente equivalente a for(int i = 0; i < int_array.length; i++) {int value = int_array[i]; /* loop content */}, o que não é o que o seu teste compara.
Daiscog
(a propósito, não estou dizendo que seu teste é inválido, mas pode valer a pena observar as razões por trás da diferença para que as pessoas possam escolher o que é certo para o seu cenário específico. Se estiverem fazendo um int value = int_array[i];no início de loop, em seguida, eles poderiam muito bem usar foreach a menos que eles precisam de acesso ao índice, também, por algum motivo em suma, tudo depende do contexto)...
daiscog
129

Aqui está uma resposta que não pressupõe conhecimento de Iteradores Java. É menos preciso, mas é útil para a educação.

Durante a programação, geralmente escrevemos um código parecido com o seguinte:

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]
}

A sintaxe foreach permite que esse padrão comum seja escrito de uma maneira mais natural e com menos ruído sintaticamente.

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

Além disso, essa sintaxe é válida para objetos como Listas ou Conjuntos que não suportam a indexação de matriz, mas que implementam a interface Iterável Java.

MRocklin
fonte
40

O loop for-each em Java usa o mecanismo do iterador subjacente. Portanto, é idêntico ao seguinte:

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

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

Nos recursos do Java 8, você pode usar isso:

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

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

Resultado

First
Second
Third
Jrovalle
fonte
7
esta informação aleatória não responde nem remotamente a questão
Tim
25

Está implícito na resposta do nsayer, mas vale a pena notar que os OP para a sintaxe (..) funcionarão quando "someList" for qualquer coisa que implemente java.lang.Iterable - não precisa ser uma lista ou uma coleção de java.util. Mesmo seus próprios tipos, portanto, podem ser usados ​​com essa sintaxe.

EfForEffort
fonte
1
fd está à direita - o código interno quando o lado direito do idioma for (:) usa int e array.length em vez de buscar um Iterator. forums.sun.com/thread.jspa?messageID=2743233
nsayer
24

Conforme definido no JLS para cada loop, pode ter duas formas:

  1. Se o tipo de Expressão for um subtipo de Iterabletradução, será a seguinte:

    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. Se a expressão necessariamente tiver um tipo de matriz, T[]então:

    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);
    }

O Java 8 introduziu fluxos com desempenho geralmente melhor. Podemos usá-los como:

someList.stream().forEach(System.out::println);
Arrays.stream(someArray).forEach(System.out::println);
akhil_mittal
fonte
2
A resposta mais relevante e precisa. Enchansed for tem duas traduções, de fato.
Zarial 23/09
23

Uma sintaxe do loop foreach é:

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

Exemplo:

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

Resultado:

Java
Coffe
Is
Cool

AVISO: Você pode acessar elementos da matriz com o loop foreach, mas NÃO pode inicializá-los. Use o forloop original para isso.

AVISO: você deve combinar o tipo da matriz com o outro objeto.

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

Se você deseja editar elementos, use o forloop original como este:

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";
}

Agora, se despejarmos s no console, obteremos:

hello
2 is cool
hello
hello
PrivateName
fonte
21

A construção de loop "for-each" do Java permitirá a iteração sobre dois tipos de objetos:

  • T[] (matrizes de qualquer tipo)
  • java.lang.Iterable<T>

A Iterable<T>interface tem apenas um método: Iterator<T> iterator(). Isso funciona em objetos do tipo Collection<T>porque a Collection<T>interface se estende Iterable<T>.

Ryan Delucchi
fonte
16

O conceito de um loop foreach, conforme mencionado na Wikipedia, é destacado abaixo:

Diferentemente de outras construções for loop, no entanto, os loops foreach geralmente não mantêm um contador explícito : eles dizem essencialmente "faça isso com tudo neste conjunto", em vez de "faça isso x vezes". Isso evita possíveis erros pontuais e torna o código mais simples de ler.

Portanto, o conceito de um loop foreach descreve que o loop não usa nenhum contador explícito, o que significa que não há necessidade de usar índices para percorrer a lista, portanto, ele salva o usuário do erro de um por um. Para descrever o conceito geral desse erro de um por um, vamos dar um exemplo de um loop para percorrer uma lista usando índices.

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

}

Mas suponha que se a lista começar com o índice 1, esse loop lançará uma exceção, pois não encontrará nenhum elemento no índice 0 e esse erro será chamado de erro de um por um. Portanto, para evitar esse erro isolado, é utilizado o conceito de um loop foreach. Também pode haver outras vantagens, mas acho que esse é o principal conceito e a vantagem de usar um loop foreach.

oneConsciousness
fonte
13

No Java 8, eles introduziram o forEach. Usando a lista, o Maps pode ser repetido.

Loop uma lista usando para cada

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); 
});

Loop um mapa usando para cada

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
fonte
12
for (Iterator<String> itr = someList.iterator(); itr.hasNext(); ) {
   String item = itr.next();
   System.out.println(item);
}
Roger Lindsjö
fonte
11

Usando versões Java mais antigas, incluindo Java 7você pode usar o foreachloop da seguinte maneira.

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);
        }

A seguir, é apresentada a maneira mais recente de usar foreachloop emJava 8

(loop uma lista com forEachexpressão + lambda ou referência de método)

//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);

Para mais informações, consulte este link.

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

Dulith De Costa
fonte
10

Aqui está uma expressão equivalente.

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

Observe também que o uso do método "foreach" na pergunta original tem algumas limitações, como não poder remover itens da lista durante a iteração.

O novo loop for é mais fácil de ler e remove a necessidade de um iterador separado, mas só é realmente utilizável em passagens de iteração somente leitura.

billjamesdev
fonte
1
Nesses casos, o uso de removeIfpode ser a ferramenta certa
ncmathsadist
9

Uma alternativa ao forEach para evitar o seu "para cada":

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

Variante 1 (simples):

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

Variante 2 (execução paralela (mais rápida)):

someList.parallelStream().forEach(listItem -> {
    System.out.println(listItem);
});
Alexander Drobyshevsky
fonte
2
Deveria mencionar que ele foi adicionado no Java 1.8
TheLibrarian
Não podemos ter 100% de certeza de que o mesmo segmento é usado. Eu gosto de usar o for(formulário se quiser garantir que o mesmo thread seja usado. Eu gosto de usar o formulário de fluxo se eu quiser permitir a execução multithread.
Sombrio
8

Ele agrega beleza ao seu código, removendo toda a desordem de loop básica. Dá uma aparência limpa ao seu código, justificado abaixo.

forLaço normal :

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

Usando para cada um:

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

for-each é uma construção sobre uma coleção que implementa o Iterator . Lembre-se de que sua coleção deve implementar o Iterator ; caso contrário, você não poderá usá-lo com para cada um.

A linha a seguir é lida como " para cada TimerTask t na lista " .

for (TimerTask t : list)

Há menos chance de erros no caso de cada um. Você não precisa se preocupar em inicializar o iterador ou inicializar o contador de loop e finalizá-lo (onde há espaço para erros).

Manohar
fonte
8

Antes do Java 8, você precisa usar o seguinte:

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

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

No entanto, com a introdução do Streams no Java 8, você pode fazer a mesma coisa com muito menos sintaxe. Por exemplo, para o seu, someListvocê pode fazer:

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

Você pode encontrar mais informações sobre fluxos aqui .

stackFan
fonte
The foreach loop, added in Java 5 (also called the "enhanced for loop"), is equivalent to using a java.util.Iterator
precisa saber é o seguinte
7

Seria algo assim. Muito crocante.

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

Há um bom writeup sobre para cada na documentação da Sun .

Pete
fonte
6

Como tantas boas respostas disseram, um objeto deve implementar o Iterable interfacese desejar usar umfor-each loop.

Vou postar um exemplo simples e tentar explicar de uma maneira diferente como um for-each loop funciona.

O for-eachexemplo do loop:

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);
        }
    }
}

Então, se usarmos javappara descompilar essa classe, obteremos este exemplo 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;

Como podemos ver na última linha da amostra, o compilador converterá automaticamente o uso da for-eachpalavra-chave no uso de um Iteratorem tempo de compilação. Isso pode explicar por que o objeto, que não implementa o Iterable interface, lançará um Exceptionquando tentar usar o for-eachloop.

L Joey
fonte
6

O Java para cada loop (também conhecido como aprimorado para loop) é uma versão simplificada de um loop for. A vantagem é que há menos código para escrever e menos variáveis ​​para gerenciar. A desvantagem é que você não tem controle sobre o valor da etapa e não tem acesso ao índice do loop dentro do corpo do loop.

Eles são melhor utilizados quando o valor da etapa é um incremento simples de 1 e quando você precisa apenas acessar o elemento de loop atual. Por exemplo, se você precisar fazer um loop sobre todos os elementos de uma matriz ou coleção sem espreitar adiante ou atrás do elemento atual.

Não há inicialização do loop, nenhuma condição booleana e o valor da etapa está implícito e é um incremento simples. É por isso que eles são considerados muito mais simples do que regulares para loops.

Os loops aprimorados seguem esta ordem de execução:

1) corpo do laço

2) repita da etapa 1 até que toda a matriz ou coleção tenha sido percorrida

Exemplo - Matriz Inteira

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

A variável currentValue mantém o valor atual em loop na matriz intArray. Observe que não há valor explícito da etapa - é sempre um incremento de 1.

Pode-se pensar que os dois pontos significam "dentro". Portanto, a declaração aprimorada para loop afirma: loop over intArray e armazena o valor int da matriz atual na variável currentValue.

Resultado:

1
3
5
7
9

Exemplo - Matriz de String

Podemos usar o loop for-each para iterar sobre uma matriz de strings. A declaração do loop declara: loop sobre a matriz myStrings String e armazena o valor atual da String na variável currentString.

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

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

Resultado:

alpha
beta
gamma
delta

Exemplo - Lista

O loop for aprimorado também pode ser usado para iterar em um java.util.List da seguinte maneira:

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);
}

A declaração do loop declara: loop sobre myList List of Strings e armazena o valor atual da List em variável currentItem.

Resultado:

alpha
beta
gamma
delta

Exemplo - Conjunto

O loop for aprimorado também pode ser usado para iterar em um java.util.Set da seguinte maneira:

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);
}

A declaração do loop declara: loop over mySet Set of Strings e armazena o valor atual do Set na variável currentItem. Observe que, como esse é um conjunto, os valores duplicados da sequência não são armazenados.

Resultado:

alpha
delta
beta
gamma

Fonte: Loops em Java - Ultimate Guide

gomisha
fonte
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
fonte
3

O Java para cada idioma só pode ser aplicado a matrizes ou objetos do tipo * Iterable . Esse idioma está implícito, pois é realmente apoiado por um Iterador. O iterador é programado pelo programador e geralmente usa um índice inteiro ou um nó (dependendo da estrutura de dados) para acompanhar sua posição. No papel, é mais lento que um loop for normal, pelo menos para estruturas "lineares", como matrizes e Listas, mas fornece maior abstração.

TheArchon
fonte
-1: isso é bem menos legível (geralmente): até o seu próprio exemplo (o primeiro) está errado, pois deixa de fora o primeiro elemento do array.
Ondrej Skopek
2

Isso parece loucura, mas ei, isso funciona

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

Isso funciona. Magia

Rei Brown
fonte
1
Isso requer Java 1.8 +
BARNI
2
não responde nem remotamente a questão
Tim
2

Como muitas das outras respostas afirmam corretamente, o for each loopaçúcar sintático é apenas sobre o mesmo antigo for loope o compilador o traduz para o mesmo antigo loop for.

O javac (open jdk) possui um switch -XD-printflat, que gera um arquivo java com todo o açúcar sintático removido. o comando completo se parece com isso

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

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

Então vamos remover o açúcar sintático

Para responder a essa pergunta, criei um arquivo e escrevi duas versões for each, uma com arraye outra com a list. meu javaarquivo ficou assim.

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);
        }
    }
}

Quando compiledeste arquivo com a opção acima, obtive a seguinte saída.

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);
            }
        }
    }
}

Você pode ver que, juntamente com o outro açúcar sintático (Autoboxing) para cada loop, foi alterado para loop simples.

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

Repete todos os objetos na tabela Itens.

shubhranshu
fonte
1
O usuário não solicitou sintaxe
pradipgarala: