For-each는 새로운 구문이 아니라 Java용 구문 설탕입니다. 컴파일 타임에 컴파일러는 이 코드를 반복기 구현으로 변환하고 바이트코드로 컴파일합니다. javap-verbose-Testforeach
명령을 실행하여 다음 컴파일된 코드를 디컴파일할 수 있습니다. javap-verbose-Testforeach
反编译以下编译代码:
public class TestForeach { List<Integer> integers; public void testForeach(){ for(Integer i : integers){ } } }
获得的详细字节码如下:
public void testForeach(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=3, args_size=1 0: aload_0 1: getfield #2 // Field integers:Ljava/util/List; 4: invokeinterface #3, 1 // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator; 9: astore_1 10: aload_1 11: invokeinterface #4, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z 16: ifeq 32 19: aload_1 20: invokeinterface #5, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object; 25: checkcast #6 // class java/lang/Integer 28: astore_2 29: goto 10 32: return LineNumberTable: line 11: 0 line 13: 29 line 14: 32 LocalVariableTable: Start Length Slot Name Signature 29 0 2 i Ljava/lang/Integer; 0 33 0 this Ltest/TestForeach; }
此字节码的一般含义是使用getfileld
命令来获取integers
变量并且调用List.iterator
来获取迭代器实例和调用iterator.hasNext
。如果返回true
,调用iterator.next
public class ForLoopTest { public static void main(String[] args) { List<Integer> arrayList = new ArrayList<>(); for (int i = 0; i < 10000000; i++) { arrayList.add(i); } long arrayListStartTime = System.currentTimeMillis(); for (int i = 0; i < arrayList.size(); i++) { arrayList.get(i); } long arrayListCost =System.currentTimeMillis()-arrayListStartTime; System.out.println("ArrayList for loop traversal cost: "+ arrayListCost); long arrayListForeachStartTime = System.currentTimeMillis(); for (Integer integer : arrayList) { } long arrayListForeachCost =System.currentTimeMillis()-arrayListForeachStartTime; System.out.println("ArrayList foreach traversal cost: "+ arrayListForeachCost);얻은 자세한 바이트코드는 다음과 같습니다.
rrreee
이 바이트코드의 일반적인 의미는를 사용한다는 것입니다. getfileld
명령을 사용하여 integers
변수를 가져오고 List.iterator
를 호출하여 반복기 인스턴스를 가져오고 iterator.hasNext
를 호출합니다. true
가 반환되면 iterator.next
메서드를 호출하세요. 이것은 컬렉션을 순회하는 반복자의 구현 논리입니다. Benchmarking이제 for 루프 방식과 for-each 방식을 사용해 테스트해 보겠습니다. rrreee테스트 결과는 다음과 같습니다.
보시다시피 결과는 명백합니다. For 루프 메서드를 사용하는 것은 For Each 메서드보다 ArrayList에서 더 효율적입니다.
for 루프가 for-each보다 낫다고 말할 수 있나요?
답은 '아니오'입니다. 다음 벤치마크에서는 ArrayList를 LinkedList로 변경합니다. 다시한번 테스트 결과입니다.
원인 분석
일부 초보자는 ArrayList가 for 루프 방법을 사용하여 더 빠르게 탐색하는 반면 LinkedList는 느리고 매우 느린 이유를 궁금해할 수 있습니다.
이는 ArrayList 및 LinkedList 데이터 구조에 의해 결정됩니다.
ArrayList는 배열을 사용하여 아래에 요소를 저장합니다. 배열은 연속적인 메모리 공간입니다. 인덱스를 통해 데이터를 얻을 수 있습니다. 시간 복잡도는 O(1)이므로 빠릅니다. LinkedList의 맨 아래 레이어는 이중 연결 리스트입니다. for 루프를 사용하여 매번 연결된 목록의 헤드 노드부터 시작하여 순회를 구현합니다. 시간 복잡도는 O(n*n)입니다.위 내용은 Java 루프의 For 및 For-each 애플리케이션 비교 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!