본문 바로가기
Java & Spring

List의 값을 가져와서 다른 List에 담을 때, for-loop, iterator, Stream foreach, ParallelStream에 대하여..

by 모닝위즈 2022. 1. 13.
반응형

먼저 100000개의 String 값을 가지고 있는 리스트가 있다고 가정을 하자.

        List<String> list = new ArrayList<>();
        for(int a=0; a<100000;a++) {
            list.add(a+"번째");
        }

그리고, 각 for 반복문, 향상된 for문, iterator, Stream.foreach, 를 활용한 부분에 대하여 작성된 소스코드.

    //Iterator를 활용한 경우
    public static void userIterator(List<String> list, int loopCount){
        double[] allTime = new double[loopCount];
        for(int z=0;z<loopCount;z++){
            List<String> tList = new ArrayList<>();
            long startTime = System.nanoTime();
            Iterator it = list.iterator();
            while (it.hasNext()) {
                tList.add((String) it.next());
            }
            long endTime = System.nanoTime();
            long lTime = endTime - startTime;
            allTime[z] = (lTime/1000000.0);
        }
        reseachOut(allTime, "Iterator 활용");
    }

    //Stream Foreach를 활용한 경우
    public static void useStreamForeach(List<String> list, int loopCount){
        double[] allTime = new double[loopCount];
        for(int z=0;z<loopCount;z++){
            List<String> lList = new ArrayList<>();
            long startTime = System.nanoTime();
            list.stream().forEach(
                    (s) -> {lList.add(s);}
            );
            long endTime = System.nanoTime();
            double lTime = endTime - startTime;
            allTime[z] = (lTime/1000000.0);
        }
        reseachOut(allTime, "Stream Foreach 활용");
    }

    //Stream Collectors.toList를 활용한 경우
    public static void useStreamForeachCollectors(List<String> list, int loopCount){
        double[] allTime = new double[loopCount];
        List<String> lList = new ArrayList<>();
        for(int z=0;z<loopCount;z++){
            long startTime = System.nanoTime();
            lList = list.stream().collect(Collectors.toList());
            long endTime = System.nanoTime();
            double lTime = endTime - startTime;
            allTime[z] = (lTime/1000000.0);
        }
        reseachOut(allTime, "stream Collectors.toList 활용");
    }

    //parallelStream Collectors.toList()를 활용한 경우
    public static void useParallelStreamForeachCollectors(List<String> list, int loopCount){
        double[] allTime = new double[loopCount];
        List<String> lList = new ArrayList<>();
        for(int z=0;z<loopCount;z++){
            long startTime = System.nanoTime();
            lList = list.parallelStream().collect(Collectors.toList());
            long endTime = System.nanoTime();
            double lTime = endTime - startTime;
            allTime[z] = (lTime/1000000.0);
        }
        reseachOut(allTime, "parallelStream Collectors.toList 활용");
    }

    //일반 for문을 활용한 경우
    public static void useNormalFor(List<String> list, int loopCount){
        double[] allTime = new double[loopCount];
        for(int z=0;z<loopCount;z++){
            List<String> nList = new ArrayList<>();
            long startTime = System.nanoTime();
            for(int x=0;x<list.size();x++) {
                nList.add(list.get(x));
            }
            long endTime = System.nanoTime();
            double lTime = endTime - startTime;
            allTime[z] = (lTime/1000000.0);
        }
        reseachOut(allTime, "for 반복문 활용");
    }

    //향상된 for문을 활용한 경우
    public static void useImproveFor(List<String> list, int loopCount){
        double[] allTime = new double[loopCount];
        for(int z=0;z<loopCount;z++){
            List<String> iList = new ArrayList<>();
            long startTime = System.nanoTime();
            for(String str : list) {
                iList.add(str);
            }
            long endTime = System.nanoTime();
            double lTime = endTime - startTime;
            allTime[z] = (lTime/1000000.0);
        }
        reseachOut(allTime, "향상된 for 활용");
    }

    // n회 진행 시 걸린 타임에 대하여 최소 시간 , 최대 시간, 평균 시간을 구하여 나타내는 녀석
    public static void reseachOut(double[] allTime, String type){
        double sum = 0.0;
        double min = allTime[0];
        double max = allTime[0];
        for (int i=0; i<allTime.length; i++){
            if(min > allTime[i]){
                min = allTime[i];
            }
            if(max < allTime[i]) {
                max = allTime[i];
            }
            sum += allTime[i];
        }
        double avg = (sum/allTime.length);
        System.out.println(type+" TIME min : "+min+", max : "+max+", avg : "+avg);
    }

위 작성한 메소드를 통하여 아래의 맞게 실행을 시켜주자...

    public static void main(String[] args) throws Exception {

        //100000개의 String 값을 가지고 있는 리스트가 있다고 가정을 한다.
        List<String> list = new ArrayList<>();
        for(int a=0; a<100000;a++) {
            list.add(a+"번째");
        }

        //TODO 리스트의 값을 다른 리스트에 담을 때 걸리는 시간 체크
 
        // 일반 for문
        System.gc();
        Thread.sleep(1000);
        useNormalFor(list, 100);

        // 향상된 for문
        System.gc();
        Thread.sleep(1000);
        useImproveFor(list, 100);

        // stream foreach
        System.gc();
        Thread.sleep(1000);
        useStreamForeach(list, 100);

        // stream Collectors.toList();
        System.gc();
        Thread.sleep(1000);
        useStreamForeachCollectors(list, 100);

        // ParallelStream Collectors.toList();
        System.gc();
        Thread.sleep(1000);
        useParallelStreamForeachCollectors(list, 100);

        // Iterator 100회 진행 시
        System.gc();
        Thread.sleep(1000);
        userIterator(list, 100);
        
    }

총 100회를 진행해보았으며, 각 항목에 대하여 프로세스가 진행된 최소 시간과 최대 시간을 알아보았다.

 

Sream.foreach는 자원을 많이 먹는 것으로 유명한 만큼

초기 실행 때 43.2945ms라는 막대한(?) 시간을 소모하였다.

하지만 실행이 될 때 마다 시간이 많이 단축되는 것을 확인하였다. 

(다음 번에는 메모리를 얼마나 먹냐도 체크를 해보자) 

 

병렬처리를 위해 ParallelStream를 사용하였을 때, collect를 사용하지 않으니, 

싱크가 맞지않는지.. 데이터가 중간중간 비거나, ArrayIndexOutOfBoundsException 오류가 종종 났었다.

 

일단은 list의 값을 다른 list에 담을 때, iterator를 활용하는 편이 가장 시간적으로 절약이 되었다. 

(물론 무조건적이지는 않다.)

 

* 위 테스트는 VM option으로 -Xms1G -Xmx1G를 통하여 heap size 메모리를 1g를 할당한 상태에서 진행되었다. 

 

 

 

돈이 많다면 하드웨어 성능으로 찍어누르자.

댓글