Stream
은 for loop
에 비해 간단한 연산을 수행하는데 더 많은 시간이 걸린다고 알려져 있다.
실제로 자바로 알고리즘 문제를 풀다가 Stream
을 쓴 코드에서 TLE
를 받아 고친적도 있다.
이번에도 알고리즘 문제를 풀다 문득 궁금해져서 가볍게 다뤄보려 한다.
우선 실행한 환경은 다음과 같다.
CPU : M2 Pro
, RAM : 32GB
, Java 11
, IDE : InteliJ
비교를 해보고자 한 것은 다음과 같다.
Stream
, For Loop
, Primitive Type
, Wrapped Type
4가지에 초점을 두고 시행해봤다.
public static void printWrappedCaseWithStream() {
List<Integer> numbers = new ArrayList<>();
for (int i = 0; i < 1000000; i++) {
numbers.add(i + 1);
}
long startTime = System.nanoTime();
int sum = numbers.stream()
.mapToInt(Integer::intValue)
.sum();
long endTime = System.nanoTime();
System.out.println("Sum using Stream (wrapped type): " + sum);
System.out.println("Time taken using Stream (wrapped type): " + (endTime - startTime) + " ns\n");
}
public static void printPrimitiveCaseWithStream() {
int[] numbers = new int[1000000];
for (int i = 0; i < 1000000; i++) {
numbers[i] = i + 1;
}
long startTime = System.nanoTime();
int sum = Arrays.stream(numbers).sum();
long endTime = System.nanoTime();
System.out.println("Sum using Stream (primitive type): " + sum);
System.out.println("Time taken using Stream (primitive type): " + (endTime - startTime) + " ns\n" );
}
public static void printWrappedCaseWithForLoop() {
List<Integer> numbers = new ArrayList<>();
for (int i = 1; i <= 1000000; i++) {
numbers.add(i);
}
long startTime = System.nanoTime();
int sum = 0;
for (int num : numbers) {
sum += num;
}
long endTime = System.nanoTime();
System.out.println("Sum using for loop (wrapped type): " + sum);
System.out.println("Time taken using for loop (wrapped type): " + (endTime - startTime) + " ns");
}
public static void printPrimitiveCaseWithForLoop() {
int[] numbers = new int[1000000];
for (int i = 0; i < 1000000; i++) {
numbers[i] = i + 1;
}
long startTime = System.nanoTime();
int sum = 0;
for (int num : numbers) {
sum += num;
}
long endTime = System.nanoTime();
System.out.println("Sum using for loop (primitive type): " + sum);
System.out.println("Time taken using for loop (primitive type): " + (endTime - startTime) + " ns \n");
}
For Loop
이 Stream
에 비해 빠르고
Primitive Type
이 Wrapped Type
보다 빠르다.
Primitive Type
은 stack
영역에 저장되어 JVM이 직접 참조할 수 있지만 Wrapped Type
은 객체이기 때문에 heap
영역에 저장되기 때문에 간접참조 해야하고 이로인해 속도차이가 발생했다고 생각한다.
함수 내부의 로직이 복잡하여 계산 비용이 높다면Stream
과 For-Loop
간의 성능차이가 줄어든다고 한다.
이를 통해 개발자는 항상Trade-Off
를 고려하고 적절한 상황에 맞게끔 대처해야함을 느꼈다.
코테의 경우에는 대부분 효율성이 훨씬 중요하기에 Stream
사용에 지양해야겠다.
관련 글을 조사하다 자세하게 비교해놓은 좋은 글을 발견해서 링크를 남긴다.