etc./StackOverFlow

Java 'for each' 루프는 어떻게 작동합니까?

청렴결백한 만능 재주꾼 2022. 2. 8. 08:37
반응형

질문자 :Jay R.


고려하다:

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

for each 구문을 사용하지 않고 동등한 for 루프는 어떻게 생겼습니까?



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

i.remove(); 를 사용해야 하는 경우 유의하십시오. 루프에서 또는 어떤 방식으로 실제 반복기에 액세스할 때 실제 반복기는 단지 유추되기 때문에 for ( : )

Denis Bueno가 언급한 것처럼 이 코드는 Iterable 인터페이스 를 구현하는 모든 객체에서 작동합니다.

for (:) 관용구의 오른쪽이 Iterable array 인 경우 내부 코드는 int 인덱스 카운터를 사용하고 array.length 를 확인합니다.Java 언어 사양을 참조하십시오.


nsayer

각각에 대한 구성 은 배열에도 유효합니다. 예

 String[] fruits = new String[] { "Orange", "Apple", "Pear", "Strawberry" }; for (String fruit : fruits) { // fruit is an element of the `fruits` array. }

본질적으로 동등한

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

따라서 전체 요약은 다음과 같습니다.
[nsayer] 다음은 일어나고 있는 일의 더 긴 형태입니다.

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

i.remove()를 사용해야 하는 경우 유의하십시오. 루프에서 또는 어떤 식으로든 실제 반복기에 액세스할 때 실제 반복기는 단지 유추되기 때문에 for( : ) 관용구를 사용할 수 없습니다.

[데니스 부에노]

nsayer의 대답에 암시되어 있지만 "someList"가 java.lang.Iterable을 구현하는 모든 경우 OP의 for(..) 구문이 작동한다는 점은 주목할 가치가 있습니다. 목록 또는 일부 컬렉션일 필요는 없습니다. 자바.유틸. 따라서 사용자 고유의 유형도 이 구문과 함께 사용할 수 있습니다.


Mikezx6r

Java 5에 추가된 for-each 루프 ("향상된 for 루프"라고도 함)는 java.util.Iterator 를 사용하는 것과 동일합니다. 동일한 작업에 대한 구문 설탕입니다. 따라서 각 요소를 하나씩 차례로 읽을 때 반복자보다 항상 for-each가 더 편리하고 간결하게 선택되어야 합니다.

각각

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

반복자

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

Iterator 직접 사용해야 하는 상황이 있습니다. 예를 들어 for-each를 사용하는 동안 요소를 삭제하려고 하면 ConcurrentModificationException 발생할 수 있습니다.

For-each 대 for-loop: 기본 차이점

for-loop와 for-each의 유일한 실질적인 차이점은 인덱싱 가능한 개체의 경우 인덱스에 액세스할 수 없다는 것입니다. 기본 for 루프가 필요한 경우의 예:

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

for-each를 사용하여 별도의 int-variable 인덱스를 수동으로 생성할 수 있지만,

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

...변수 범위 가 이상적이지 않고 기본 for 루프는 이 사용 사례에 대한 표준 및 예상 형식이기 때문에 권장하지 않습니다.

For-each 대 for-loop: 성능

컬렉션에 액세스할 때 for-each는 기본 for 루프의 배열 액세스 보다 훨씬 빠릅니다. 그러나 배열에 액세스할 때(적어도 기본 및 래퍼 배열에서는) 인덱스를 통한 액세스가 훨씬 더 빠릅니다.

기본 내부 배열에 대한 반복자와 인덱스 액세스의 타이밍 차이

인덱스는 int 또는 Integer 배열에 액세스할 때 반복자보다 23~40% 빠릅니다. 다음은 이 게시물의 맨 아래에 있는 테스트 클래스의 출력으로, 요소가 100개 있는 primitive-int 배열(A는 반복자, B는 인덱스)의 숫자를 합산합니다.

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

Integer 배열에 대해서도 이 작업을 실행했으며 인덱스가 여전히 확실한 승자이지만 18~25%만 더 빠릅니다.

컬렉션의 경우 반복자는 인덱스보다 빠릅니다.

List of Integers 경우 반복자가 확실한 승자입니다. 테스트 클래스의 내부 배열을 다음과 같이 변경하십시오.

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

그리고 test-function( int[] 에서 List<Integer> , length 에서 size() 등)에 필요한 변경을 수행하십시오.

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

한 테스트에서는 거의 동일하지만 컬렉션에서는 iterator가 이깁니다.

*이 게시물은 스택 오버플로에 대해 작성한 두 가지 답변을 기반으로 합니다.

추가 정보: for-each 루프와 반복자 중 어느 것이 더 효율적입니까?

전체 테스트 클래스

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;https://stackoverflow.com/questions/180158/how-do-i-time-a-methods-execution-in-java&quot;&gt;https://stackoverflow.com/questions/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

다음은 Java Iterator에 대한 지식을 가정하지 않는 답변입니다. 덜 정확하지만 교육에 유용합니다.

프로그래밍하는 동안 우리는 종종 다음과 같은 코드를 작성합니다.

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

foreach 구문을 사용하면 이 공통 패턴을 보다 자연스럽고 구문적으로 덜 시끄러운 방식으로 작성할 수 있습니다.

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

또한 이 구문은 배열 인덱싱을 지원하지 않지만 Java Iterable 인터페이스를 구현하는 목록 또는 집합과 같은 객체에 유효합니다.


MRocklin

Java의 for-each 루프는 기본 반복자 메커니즘을 사용합니다. 따라서 다음과 동일합니다.

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

toluju

JLS for-each 루프에 정의된 대로 두 가지 형식이 있을 수 있습니다.

  1. 식의 유형이 Iterable 의 하위 유형인 경우 변환은 다음과 같습니다.

     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. 표현식에 반드시 배열 유형 T[] 다음을 수행합니다.

     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은 일반적으로 하강 크기 데이터 세트에서 더 나은 성능을 보이는 스트림을 도입했습니다. 다음과 같이 사용할 수 있습니다.

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

akhil_mittal

nsayer의 대답에 암시되어 있지만 "someList"가 java.lang.Iterable을 구현하는 모든 경우 OP의 for(..) 구문이 작동한다는 점은 주목할 가치가 있습니다. 목록 또는 일부 컬렉션일 필요는 없습니다. 자바.유틸. 따라서 사용자 고유의 유형도 이 구문과 함께 사용할 수 있습니다.


EfForEffort

foreach 루프 구문은 다음과 같습니다.

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

예시:

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

산출:

 Java Coffe Is Cool

경고: foreach 루프를 사용하여 배열 요소에 액세스할 수 있지만 초기화할 수는 없습니다. 이를 위해 원래 for 루프를 사용하십시오.

경고: 배열 유형을 다른 개체와 일치시켜야 합니다.

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

요소를 편집하려면 다음과 같이 for

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

이제 콘솔에 s를 덤프하면 다음을 얻습니다.

 hello 2 is cool hello hello

PrivateName

Java 8 기능에서는 다음을 사용할 수 있습니다.

 List<String> messages = Arrays.asList("First", "Second", "Third"); void forTest(){ messages.forEach(System.out::println); }

산출

 First Second Third

Jrovalle

Java "for-each" 루프 구조는 두 가지 유형의 객체에 대한 반복을 허용합니다.

  • T[] (모든 유형의 배열)
  • java.lang.Iterable<T>

Iterable<T> Iterator<T> iterator() 메서드가 하나만 있습니다. 유형의 개체에이 작품 Collection<T> 때문에 Collection<T> 인터페이스는 확장 Iterable<T> .


Ryan Delucchi

Wikipedia에서 언급한 foreach 루프의 개념은 아래에 강조 표시되어 있습니다.

그러나 다른 for 루프 구조와 달리 foreach 루프는 일반적으로 명시적 카운터를 유지하지 않습니다. 기본적으로 "이 작업을 x번 수행"하는 대신 "이 집합의 모든 항목에 대해 수행"이라고 말합니다. 이렇게 하면 잠재적인 off-by-one 오류를 방지 하고 코드를 더 쉽게 읽을 수 있습니다.

따라서 foreach 루프의 개념은 루프가 명시적 카운터를 사용하지 않는다는 것을 설명합니다. 즉, 목록을 탐색하기 위해 인덱스를 사용할 필요가 없으므로 사용자가 하나씩 오류가 발생하지 않도록 합니다. 이 off-by-one 오류의 일반적인 개념을 설명하기 위해 인덱스를 사용하여 목록에서 순회하는 루프의 예를 들어보겠습니다.

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

그러나 목록이 인덱스 1로 시작하는 경우 이 루프는 인덱스 0에서 요소를 찾지 못하므로 예외가 발생하고 이 오류를 오프바이원 오류라고 가정합니다. 따라서 이러한 개별 오류를 피하기 위해 foreach 루프의 개념이 사용됩니다. 다른 장점도 있을 수 있지만 이것이 foreach 루프를 사용하는 주요 개념이자 장점이라고 생각합니다.


oneConsciousness

Java 8에서는 forEach를 도입했습니다. 목록을 사용하여 지도를 반복할 수 있습니다.

for each를 사용하여 목록을 반복합니다.

 List<String> someList = new ArrayList<String>(); someList.add("A"); someList.add("B"); someList.add("C"); someList.forEach(listItem -> System.out.println(listItem))

또는

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

for each를 사용하여 맵 루프

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

또는

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

vivekkurien

다음은 이에 상응하는 표현입니다.

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

Hank

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



Java 7 을 포함한 이전 Java 버전을 사용하면 다음과 같이 foreach 루프를 사용할 수 있습니다.

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

Java 8 에서 foreach 루프를 사용하는 최신 방법입니다.

forEach + 람다 식 또는 메서드 참조를 사용하여 목록을 루프)

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

자세한 내용은 이 링크를 참조하십시오.

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


Dulith De Costa

또한 원래 질문에서 "foreach" 방법을 사용하면 반복하는 동안 목록에서 항목을 제거할 수 없는 것과 같은 몇 가지 제한 사항이 있습니다.

새로운 for 루프는 읽기가 더 쉽고 별도의 반복자가 필요하지 않지만 읽기 전용 반복 단계에서만 실제로 사용할 수 있습니다.


billjamesdev

"for each"를 피하기 위한 forEach의 대안:

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

변형 1(일반):

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

변형 2(병렬 실행(더 빠름)):

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

Alexander Drobyshevsky

모든 기본 루핑 어수선함을 제거하여 코드에 아름다움을 더합니다. 아래에서 정당화되는 코드에 깔끔한 모습을 제공합니다.

루프에 for 일반:

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

for-each 사용:

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

for-each 는 Iterator 를 구현하는 컬렉션에 대한 구성입니다. 컬렉션이 Iterator 를 구현해야 함을 기억하십시오. 그렇지 않으면 for-each와 함께 사용할 수 없습니다.

다음 줄은 " for each TimerTask t in list. "로 읽습니다.

 for (TimerTask t : list)

for-each의 경우 오류 가능성이 적습니다. 반복자를 초기화하거나 루프 카운터를 초기화하고 종료하는 것에 대해 걱정할 필요가 없습니다(오류의 범위가 있는 경우).


Manohar

Java 8 이전에는 다음을 사용해야 합니다.

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

그러나 Java 8에 Streams가 도입되면 훨씬 더 적은 구문으로 동일한 작업을 수행할 수 있습니다. 예를 들어 someList 대해 다음을 수행할 수 있습니다.

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

여기에서 스트림에 대해 자세히 알아볼 수 있습니다.


stackFan

다음과 같이 보일 것입니다. 매우 잔인합니다.

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

Sun 문서 에 각각 에 대한 좋은 기록이 있습니다.


Pete

많은 좋은 답변이 말했듯이 객체는 for-each 루프를 사용 Iterable interface

for-each 루프가 어떻게 작동하는지 다른 방식으로 설명하려고 합니다.

for-each 루프의 예:

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

그런 다음 javap 를 사용하여 이 클래스를 디컴파일하면 다음 바이트 코드 샘플을 얻을 수 있습니다.

 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;

샘플의 마지막 줄에서 볼 수 있듯이 컴파일러는 컴파일 시간 for-each 키워드 사용을 Iterator Iterable interface for-each 루프를 사용하려고 할 때 Exception 발생하는 이유를 설명할 수 있습니다.


L Joey

각 루프에 대한 Java (향상된 for 루프라고도 함)는 for 루프의 단순화된 버전입니다. 장점은 작성할 코드와 관리할 변수가 적다는 것입니다. 단점은 단계 값을 제어할 수 없고 루프 본문 내부의 루프 인덱스에 액세스할 수 없다는 것입니다.

단계 값이 1의 단순 증분일 때와 현재 루프 요소에만 액세스해야 할 때 가장 잘 사용됩니다. 예를 들어 현재 요소의 앞이나 뒤를 엿보지 않고 배열이나 컬렉션의 모든 요소를 반복해야 하는 경우입니다.

루프 초기화, 부울 조건 및 단계 값은 암시적이며 단순 증분입니다. 이것이 일반 for 루프보다 훨씬 간단하다고 여겨지는 이유입니다.

향상된 for 루프는 다음 실행 순서를 따릅니다.

1) 루프 바디

2) 전체 배열 또는 컬렉션이 순회될 때까지 1단계부터 반복합니다.

예 – 정수 배열

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

currentValue 변수는 intArray 배열에서 반복되는 현재 값을 보유합니다. 명시적인 단계 값이 없다는 점에 유의하세요. 항상 1씩 증가합니다.

콜론은 "안에"를 의미한다고 생각할 수 있습니다. 따라서 향상된 for 루프 선언 상태: intArray를 반복하고 현재 배열 int 값 currentValue 변수에 저장합니다.

산출:

 1 3 5 7 9

예 – 문자열 배열

for-each 루프를 사용하여 문자열 배열을 반복할 수 있습니다. 루프 선언 상태: myStrings String 배열을 반복하고 현재 String 값 currentString 변수에 저장합니다.

 String [] myStrings = { "alpha", "beta", "gamma", "delta" }; for(String currentString : myStrings) { System.out.println(currentString); }

산출:

 alpha beta gamma delta

예 – 목록

향상된 for 루프를 사용하여 다음과 같이 java.util.List를 반복할 수도 있습니다.

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

루프 선언 상태: myList 문자열 목록을 반복하고 현재 목록 값 currentItem 변수에 저장합니다.

산출:

 alpha beta gamma delta

예 – 설정

향상된 for 루프를 사용하여 다음과 같이 java.util.Set를 반복할 수도 있습니다.

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

루프 선언 상태: mySet 문자열 집합을 반복하고 현재 Set 값 currentItem 변수에 저장합니다. 이것은 Set이기 때문에 중복된 String 값은 저장되지 않습니다.

산출:

 alpha delta beta gamma

출처: Java의 루프 – 궁극적인 가이드


gomisha

다른 많은 답변이 올바르게 명시되어 있듯이 for each loop 는 동일한 이전 for loop 대한 구문 설탕이며 컴파일러는 이를 동일한 이전 for 루프로 변환합니다.

javac(open jdk)에는 모든 구문 설탕이 제거된 Java 파일을 생성하는 -XD-printflat 완전한 명령은 다음과 같습니다

 javac -XD-printflat -d src/ MyFile.java //-d is used to specify the directory for output java file

따라서 구문 설탕을 제거합시다.

이 질문에 답하기 위해 파일을 만들고 each for 두 가지 버전을 작성했습니다. 하나는 array 이고 다른 list 입니다. 내 java 파일은 다음과 같습니다.

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

위의 스위치를 사용하여 이 파일을 compiled 했을 때 다음과 같은 출력을 얻었습니다.

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

각 루프에 대한 다른 구문 설탕(Autoboxing)과 함께 간단한 루프로 변경된 것을 볼 수 있습니다.


mightyWOZ

public static Boolean Add_Tag(int totalsize) { List<String> fullst = new ArrayList<String>(); for(int k=0;k<totalsize;k++) { fullst.addAll(); } }

Santhosh Rajkumar

Java for-each 관용구는 *Iterable 유형의 배열 또는 객체에만 적용할 수 있습니다. 이 관용구는 Iterator가 진정으로 뒷받침하기 때문에 암시적입니다. Iterator는 프로그래머에 의해 프로그래밍되며 종종 정수 인덱스 또는 노드(데이터 구조에 따라 다름)를 사용하여 위치를 추적합니다. 문서상에서는 배열 및 목록과 같은 "선형" 구조의 경우 일반 for 루프보다 느리지만 더 큰 추상화를 제공합니다.


TheArchon

이것은 미친 것처럼 보이지만 작동합니다.

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

이것은 작동합니다. 마법


Rei Brown

나는 이것이 효과가 있다고 생각합니다.

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

nabayram

코드는 다음과 같습니다.

 import java.util.ArrayList; import java.util.List; public class ForLoopDemo { public static void main(String[] args) { List<String> someList = new ArrayList<String>(); someList.add("monkey"); someList.add("donkey"); someList.add("skeleton key"); //Iteration using For Each loop System.out.println("Iteration using For Each loop:"); for (String item : someList) { System.out.println(item); } //Iteration using normal For loop System.out.println("\nIteration using normal For loop:"); for (int index = 0; index < someList.size(); index++) { System.out.println(someList.get(index)); } } }

Java-Dev

출처 : http:www.stackoverflow.com/questions/85190/how-does-the-java-for-each-loop-work

반응형