Adventure Time - Finn 3

ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Stream vs for loop
    Java & Spring 2024. 5. 19. 16:06

    Java 8부터 사용이 가능한 Stream은 배열과 Collection의 데이터 처리에 초점을 둔 기능이다.

    평소에 나는 업무 시 코드량을 줄이고 가독성을 높이려고 Stream을 사용하곤 했다. 알고리즘을 풀때면 for 문을 줄줄이 쓰기보단 단 몇줄의 Stream을 좀 더 선호했었다. 그러다가 Stream을 사용하다 제한시간을 통과하지 못한 케이스가 있어, Stream과 전통적인 loop을 비교해 알아봤다.

    결론부터 말하자면, Stream은 일단 테스트 데이터가 매우 많아야 효율적이다. 또는 각 원소마다 컴퓨팅 연산이 오래 걸릴 수록 Stream 사용이 적합하다. 그렇다고 for loop이 나쁘냐? 그것도 아니다. for loop이 일반적으로 Stream보다 빠르다.

    내가 파악하기로 Stream보다 for loop의 성능이 더 떨어지는 경우는 다음 조건일 때다.

    1. 각 원소마다의 연산이 오래걸린다. (아파치 라이브러리의 slowSin() 같은.... )

    2. 병렬 Stream이 가능한 경우 (연산이 오래걸리면 병렬 처리할 때가 더 빠른 경우가 있다. LinkedList 연산은 병렬스트림이 더 느림....)

    그 외에는 Stream 성능이 좀 더 뒤쳐지거나, 비슷한 (데이터가 많을 경우) 수준이다.

     

    프로그래머스 최댓값과 최솟값 문제를 전에 Stream으로 풀었던게 생각나서 for loop로 풀었을 때랑 비교해봤다.

    <Stream 풀이>

    public static String solution(String s) {
            long startTime = System.currentTimeMillis();
    
            String[] numArr = s.split(" ");
            int max = Arrays.stream(numArr)
                            .mapToInt(n -> Integer.valueOf(n))
                            .max().getAsInt();
    
            int min = Arrays.stream(numArr)
                    .mapToInt(n -> Integer.valueOf(n))
                    .min().getAsInt();
    
            long endTime = System.currentTimeMillis();
            System.out.println((endTime - startTime));
            return min + " " + max;
    
    }
    
     public static void main(String[] args) {
     		// Stream으로 풀이했을 경우 시간
            //String s = "1 2 3 4";       // 44ms
            //String s = "-1 -2 -3 -4";   // 42ms 
            //String s = "-1 -1";         // 43ms
            
            System.out.println(solution(s));
    }

     

    < for loop 풀이 >

    public static String solution2(String s){
         long startTime = System.currentTimeMillis();
         String[] numArr = s.split(" ");
         int max = Integer.valueOf(numArr[0]);
         int min = Integer.valueOf(numArr[0]);
         int temp;
    
         for(int i = 0; i<numArr.length; i++){
              temp = Integer.valueOf(numArr[i]);
            if(max < temp){
                    max = temp;
            }
         }
    
         for(int i = 0; i<numArr.length; i++){
             temp = Integer.valueOf(numArr[i]);
             if(min > temp){
                 min = temp;
             }
         }
    
         long endTime = System.currentTimeMillis();
         System.out.println((endTime - startTime));
    
         return min + " " + max;
    }
    
    public static void main(String[] args) {
            //String s = "1 2 3 4";       // 1ms
            //String s = "-1 -2 -3 -4";   // 1ms
            //String s = "-1 -1";         // 1ms
    
            System.out.println(solution2(s));
    }

     

    스트림이 훨씬 느린것을 볼 수 있다. 데이터 수 가 일단 매우 적고, 원소별 연산이 어렵지 않기 때문에 스트림 풀이는 정답은 맞았으나, 잘못된? 선택이었던거 같다. 

    스트림은 대용량 데이터처리 + CPU 성능까지 이용할 상황에 적합한 것 같다. 그리고 스트림의 단점(?)이라기 보단 함수형 프로그래밍의 단점이라고 생각하는 부분이.... 디버깅하기가 좀 귀찮다... for loop에 비해...

    하지만 코드량을 줄이고 가독성을 높일 수 있음에는 이견이 없다. 알고리즘 공부에는 뭐 내입맛대로 하겠지만, 업무에서 사용할때는 성능을 중요시 하는 상황인지, 코드 유지보수를 중요시 하는지를 좀 따져보고 사용하면 될 것 같다.

    <참고>

    https://sigridjin.medium.com/java-stream-api%EB%8A%94-%EC%99%9C-for-loop%EB%B3%B4%EB%8B%A4-%EB%8A%90%EB%A6%B4%EA%B9%8C-50dec4b9974b

    'Java & Spring' 카테고리의 다른 글

    API 에러 응답 논쟁  (2) 2024.09.19
    EDI 구축 회고록  (1) 2024.08.29
    소셜 로그인 회고 (Spring Security)  (0) 2024.02.04

    댓글

Designed by Tistory.