Java에서 배열을 반복하는 가장 빠른 방법 : loop ariable vs 명령문 [Duplication
-
06-07-2019 - |
문제
이 질문은 이미 여기에 답이 있습니다.
Java에서는 구식 방식의 배열을 통해 반복하는 것이 더 빠릅니다.
for (int i = 0; i < a.length; i++)
f(a[i]);
또는 더 간결한 형태를 사용하여
for (Foo foo : a)
f(foo);
Arraylist의 경우 답이 동일합니까?
물론 방대한 적용 코드의 경우, 대답은 식별 할 수있는 차이가 없으므로 더 간결한 형태를 가독성에 사용해야한다는 것입니다. 그러나 제가보고있는 맥락은 수십억 번 수행 해야하는 작업을 수행 해야하는 중대한 기술 계산이므로 작은 속도 차이조차도 중요 할 수 있습니다.
해결책
배열을 통해 반복되는 경우, 고리를 위해 향상된 루프는 어쨌든 배열 액세스를 사용합니다.
예를 들어이 코드를 고려하십시오.
public static void main(String[] args)
{
for (String x : args)
{
System.out.println(x);
}
}
분해 될 때 javap -c Test
우리는 ( main
방법):
public static void main(java.lang.String[]);
Code:
0: aload_0
1: astore_1
2: aload_1
3: arraylength
4: istore_2
5: iconst_0
6: istore_3
7: iload_3
8: iload_2
9: if_icmpge 31
12: aload_1
13: iload_3
14: aaload
15: astore 4
17: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
20: aload 4
22: invokevirtual #3; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
25: iinc 3, 1
28: goto 7
31: return
이제 명시적인 배열 액세스를 사용하려면 변경하십시오.
public static void main(String[] args)
{
for (int i = 0; i < args.length; i++)
{
System.out.println(args[i]);
}
}
이것은 다음과 컴파일합니다.
public static void main(java.lang.String[]);
Code:
0: iconst_0
1: istore_1
2: iload_1
3: aload_0
4: arraylength
5: if_icmpge 23
8: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
11: aload_0
12: iload_1
13: aaload
14: invokevirtual #3; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
17: iinc 1, 1
20: goto 2
23: return
루프를 위해 향상된 설정 코드가 조금 더 많지만 기본적으로 동일한 작업을 수행하고 있습니다. 반복자가 관여하지 않습니다. 또한, 나는 그들이 더 유사한 코드로 Jitted를 얻을 것으로 기대합니다.
제안 : 정말로 그것이 큰 차이를 만들 수 있다고 생각한다면 항상 루프의 본문이 절대적으로 미미하다면) 실제 응용 프로그램으로 벤치마킹해야합니다. 그것이 중요한 상황입니다.
다른 팁
이것은 경기장에 정사각형입니다 미세 최적화. 정말 중요하지 않습니다. 스타일 적으로 나는 다른 것에 대한 루프 카운터가 필요하지 않으면 더 간결하기 때문에 항상 두 번째를 선호합니다. 그리고 그게 이런 종류의 미세 최적화보다 훨씬 중요합니다: 가독성.
즉, 배열 목록의 경우 큰 차이는 없지만 링크 사전 목록은 두 번째로 훨씬 더 효율적일 것입니다.
측정하십시오. 모든 성능 질문에 대한 답은 VM 버전, 프로세서, 메모리 속도, 캐시 등에 따라 달라질 수 있으므로 특정 플랫폼에 대해 측정해야합니다.
개인적으로 나는 의도가 더 분명하기 때문에 두 번째 변형을 선호합니다. 성능이 문제가되면 어쨌든 나중에 최적화 할 수 있습니다. 해당 코드가 실제로 전체 응용 프로그램의 성능에 중요하다면 실제로 중요합니다.
Linkedlist의 경우 :
for(ClassOfElement element : listOfElements) {
System.out.println(element.getValue());
}
이전에 답했습니다.
배열 또는 RandomAccess 컬렉션에서는 다음을 통해 속도가 약간 증가 할 수 있습니다.
List<Object> list = new ArrayList<Object>();
for (int i=0, d=list.size(); i<d; i++) {
something(list.get(i));
}
그러나 나는 일반적으로 걱정하지 않을 것입니다. 이와 같은 최적화는 코드와 0.1% 이상 차이를 만들지 않습니다. Java를 호출해보십시오 -prof 코드가 실제로 시간을 보내는 위치를 확인합니다.
더 빠르게 포크 조인 프레임 워크의 평행 배열을 사용하는 것이 더 빠릅니다 (충분히 큰 데이터 세트가있는 경우).