>  기사  >  Java  >  Java 루프의 For 및 For-each 애플리케이션 비교 분석

Java 루프의 For 및 For-each 애플리케이션 비교 분석

王林
王林앞으로
2023-05-25 14:56:081179검색

for-each 구현 방법

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 방식을 사용해 테스트해 보겠습니다.

rrreeeJava 루프의 For 및 For-each 애플리케이션 비교 분석테스트 결과는 다음과 같습니다.

보시다시피 결과는 명백합니다. For 루프 메서드를 사용하는 것은 For Each 메서드보다 ArrayList에서 더 효율적입니다.


for 루프가 for-each보다 낫다고 말할 수 있나요?

답은 '아니오'입니다. 다음 벤치마크에서는 ArrayList를 LinkedList로 변경합니다. Java 루프의 For 및 For-each 애플리케이션 비교 분석다시한번 테스트 결과입니다.

원인 분석


일부 초보자는 ArrayList가 for 루프 방법을 사용하여 더 빠르게 탐색하는 반면 LinkedList는 느리고 매우 느린 이유를 궁금해할 수 있습니다.

이는 ArrayList 및 LinkedList 데이터 구조에 의해 결정됩니다.

ArrayList는 배열을 사용하여 아래에 요소를 저장합니다. 배열은 연속적인 메모리 공간입니다. 인덱스를 통해 데이터를 얻을 수 있습니다. 시간 복잡도는 O(1)이므로 빠릅니다.

LinkedList의 맨 아래 레이어는 이중 연결 리스트입니다. for 루프를 사용하여 매번 연결된 목록의 헤드 노드부터 시작하여 순회를 구현합니다. 시간 복잡도는 O(n*n)입니다.
  • 결론

  • for-each는 반복자로 구현되고 동시 수정 확인을 수행해야 하기 때문에 ArrayList를 사용할 때 for 루프 방법이 더 빠릅니다.

  • LinkedList를 사용할 때 LinkedList는 이중 연결 목록을 사용하여 구현되므로 for-each가 for 루프보다 훨씬 빠릅니다. 모든 주소 지정은 헤드 노드에서 시작되어야 합니다. LinkedList를 순회할 때 for 루프를 사용하지 마십시오.

반복자 패턴을 사용하면 for-each는 컬렉션의 특정 구현에 신경 쓸 필요가 없습니다. 컬렉션을 교체해야 하는 경우 코드를 수정하지 않고도 쉽게 수행할 수 있습니다. 🎜🎜🎜

위 내용은 Java 루프의 For 및 For-each 애플리케이션 비교 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제