[프로그래머스 - JAVA] Lv.0 머쓱이보다 키 큰 사람
문제
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
풀이1 - for
class Solution {
public int solution(int[] array, int height) {
int answer = 0;
for(int other:array){
if(height<other) answer++;
}
return answer;
}
}
풀이2 - stream API
import java.util.Arrays;
class Solution {
public int solution(int[] array, int height) {
return (int)Arrays.stream(array)
.filter(p -> p>height)
.count();
}
}
메모
프로그래머스의 풀이를 보아도 for문과 stream 사이에 이런저런 말이 많다.이전 문제를 풀면서 단순히 stream의 메리트는 가독성이라고 생각했다.그런데 프로그래머스에 이러한 댓글이 있었다.
" 원시 타입의 경우 컴파일러 최적화 문제로 for-loop가 스트림에 비해 훨씬 빠르고,참조 타입의 경우도 for-loop가 조금 더 빠르다.하지만 순회하는 비용보다 연산하는 비용이 높아질수록 stream이 for-loop에 비해서 빨라진다"
원시 타입이란❓
원시 타입(Primitive Type)은 메모리에 값 자체를 저장하는 것으로 총 8가지가 있다.
byte, short, int, long, float, double, char, boolean
이 경우에는 Stream 내부에서 int -> Integer 으로 오토박싱 한 후
Integer -> int로 언박싱하기 때문에 추가적인 함수 호출이 많아
for-loop가 훨씬 빠르다.
오늘 선정한 문제에서도 int를 다루었기 때문에 for-loop가 더 효율적이라고 할 수 있다.
참조 타입이란❓
참조 타입(Reference Type)은 메모리에 객체의 주소를 저장하는 것이다.
대표적인 예시로 String이 있는데
이 경우에는 오토박싱/언박싱과정이 없기 때문에 원시타입과 비교하면 큰 차이가 나지 않는다.
하지만 Stream은 for-loop에 비해 스트림 객체도 생성하고 최적화가 어려워 대게 느리다.
연산이 클 때란 언제인가❓
순회를 할 때 각 단계에서 수행해야 하는 연산 비용이 크면
Stream은 내부적으로 병렬 처리 최적화가 가능하기 때문에
연산이 무거우면 for-loop보다 스트림이 빠를 수 있다.
[연산이 클 때의 예시]
Math.pos(num, 2)연산이 단순 순회보다 오래 걸린다.
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
// for-loop
int sum1 = 0;
for (int num : numbers) {
sum1 += Math.pow(num, 2);
}
// Stream
int sum2 = numbers.stream()
.mapToInt(num -> (int) Math.pow(num, 2))
.sum();