IT/development

[java] ์ง์ ‘ ๊ตฌํ˜„ํ•œ List ์ถ”์ƒํ™” (feat. ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…)

์–ดํฅ๊ผฌ๋น„ 2025. 1. 5.

๋ชฉ์ฐจ

    ๋ณต์žกํ•œ ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฐ์น˜ ํ”„๋กœ๊ทธ๋žจ์ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•œ๋‹ค.

    ๋กœ์ง์€ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋„˜์–ด์˜จ ์ธ์ž๋งŒํผ ๋ฃจํ”„๋ฅผ ๋Œ๋ฉด์„œ list์˜ ์•ž๋ถ€๋ถ„์— ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ๋Š” ๋กœ์ง์ด๋‹ค.(์•ž๋ถ€๋ถ„์ธ๊ฒŒ ์ค‘์š”)

    ๋ฐฐ์น˜ํ”„๋กœ๊ทธ๋žจ ์ฝ”๋“œ๋ฅผ ์ ์  ๊ฐœ๋ฐœ์ž๋“ค์ด ๋ฆฌํŒฉํ† ๋ง ํ–ˆ๋‹ค๋Š” ์Šคํ† ๋ฆฌ๋‹ค.

    Ver 1: ArrayList ์‚ฌ์šฉ์˜ ์„ฑ๋Šฅ ๋ฌธ์ œ

    package collection.test;
    
    import collection.list.MyArrayList;
    
    public class BatchProcessorV1 {
        // MyArrayList์— ์ง์ ‘ ์˜์กด(bad)
        private final MyArrayList<Integer> list = new MyArrayList<>();
        //์—„์ฒญ ๋ณต์žกํ•œ ๋กœ์ง์ด๋ผ๊ณ  ๊ฐ€์ •
        public void logic(int size) {
            long startTime = System.currentTimeMillis();
            //์—…๋ฌด๋ฅผ ํ•˜๋‹ค๋ณด๋‹ˆ ๋ฆฌ์ŠคํŠธ์˜ ์•ž๋ถ€๋ถ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฝ์ž…ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•„ ๋ฐฐ์—ด๋ฆฌ์ŠคํŠธ๋ณด๋‹ค Linkedlist๊ฐ€ ๋” ๋‚ซ๊ฒ ๋‹ค๋А ํŒ๋‹จ์ด ๋“ค์–ด์„œ ์ฝ”๋“œ๋ฅผ ๊ณ ์ณ์•ผ ๊ฒ ๋‹ค๊ณ  ๋งˆ์Œ์„ ๋จน์Œ
            //๊ทธ๋ž˜์„œ ์ฝ”๋“œ๋ฅผ ๊ฐœ์„ ํ•˜๊ฒŒ ๋˜๊ณ  ๊ทธ๊ฒŒ BatchProcessorV2๊ฐ€ ๋จ
            for (int i = 0; i < size; i++) {
                list.add(0, i);
            }
            long endTime = System.currentTimeMillis();
            System.out.println("ํฌ๊ธฐ: " + size + ", ๊ณ„์‚ฐ์‹œ๊ฐ„: " + (endTime - startTime) + "ms");
        }
    }

    ์ œ์ผ ๋จผ์ € MyArrayList๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฐฐ์น˜ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰์‹œํ‚จ ์ฝ”๋“œ๋‹ค.

    ์ด๋ ‡๊ฒŒ ์ž‘์„ฑํ•œ ํ”„๋กœ๊ทธ๋žจ์„ ์‹ค์ œ ๋Œ๋ฆฌ๋‹ค ๋ณด๋‹ˆ ์„ฑ๋Šฅ์ด์Šˆ๊ฐ€ ๋ฐœ์ƒํ•ด์„œ ์•„๋ž˜์™€ ๊ฐ™์ด ๊ฐœ์„ ์‹œ์ผฐ๋‹ค.

    ArrayList๋Š” ์•ž๋ถ€๋ถ„์— ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊ธฐ์กด ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ์นธ์”ฉ ๋’ค๋กœ ๋ฐ€์–ด์•ผ ๋˜๋Š” ์—ฐ์‚ฐ์ด ๋ฐœ์ƒํ•ด์„œ ๋А๋ฆฌ๋‹ค.

    1์ฐจ ๋ฆฌํŒฉํ† ๋ง (Ver 2: LinkedList๋กœ ๊ฐœ์„ )

    package collection.test;
    
    import collection.list.MyLinkedList;
    
    public class BatchProcessorV2 {
        // LinkedList๋กœ ๋ฐ”๊ฟ”์„œ ์„ฑ๋Šฅ์€ ๋งŽ์ด ๊ฐœ์„ ๋˜์—ˆ์Œ
        // ํ•˜์ง€๋งŒ ์ด ์ฝ”๋“œ๋„ ์—ฌ์ „ํžˆ BatchProcessorํด๋ž˜์Šค๊ฐ€ MyLinkedList์— ์ง์ ‘์ ์œผ๋กœ ์˜์กดํ•˜๊ณ  ์žˆ์–ด์„œ ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ์ƒ๊ธฐ๋ฉด ์ด ์ฝ”๋“œ๋ฅผ ๋˜ ์ˆ˜์ •ํ•ด์•ผ ํ•จ
        // ์ด๋ฅผ ๋‹คํ˜•์„ฑ๊ณผ ์ œ๋„ค๋ฆญ์„ ์ด์šฉํ•ด์„œ ๊ฐœ์„ ํ•ด๋ณด๊ฒ ์Œ
        // ๊ทธ ์ฝ”๋“œ๊ฐ€ BatchProcessorV3์ž„
        private final MyLinkedList<Integer> list = new MyLinkedList<>();
        //์—„์ฒญ ๋ณต์žกํ•œ ๋กœ์ง์ด๋ผ๊ณ  ๊ฐ€์ •
        public void logic(int size) {
            long startTime = System.currentTimeMillis();
            for (int i = 0; i < size; i++) {
                list.add(0, i);
            }
            long endTime = System.currentTimeMillis();
            System.out.println("ํฌ๊ธฐ: " + size + ", ๊ณ„์‚ฐ์‹œ๊ฐ„: " + (endTime - startTime) + "ms");
        }
    }

    ์ฝ”๋“œ๋ฅผ 1์ฐจ ๋ฆฌํŒฉํ† ๋ง ํ•ด์„œ ์„ฑ๋Šฅ์ด์Šˆ๋Š” ๋งŽ์ด ์ค„์–ด๋“ค์—ˆ์ง€๋งŒ ์—ฌ์ „ํžˆ ๋ฐฐ์น˜ ํ”„๋กœ๊ทธ๋žจ์ด LinkedList๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ์ง์ ‘ ์˜์กดํ•˜๊ณ  ์žˆ์–ด์„œ ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ์ƒ๊ธฐ๋ฉด ๋ฐฐ์น˜ ํ”„๋กœ๊ทธ๋žจ์˜ ์ฝ”๋“œ๋ฅผ ๋˜ ์ˆ˜์ •ํ•ด์•ผ ๋œ๋‹ค.

    ๊ณ ๋ฏผํ•˜๊ณ  ์žˆ๋˜ ์ฐฐ๋‚˜ ์žฌ์•ผ์˜ ํ•œ ์‹œ๋‹ˆ์–ด ๊ฐœ๋ฐœ์ž๊ฐ€ ๋‹ค์‹œ ์ฝ”๋“œ๋ฅผ ๊ฐœ์„ ํ•˜๊ณ  ์œ ์œ ํžˆ ๋– ๋‚ฌ๋‹ค.

    2์ฐจ ๋ฆฌํŒฉํ† ๋ง (Ver 3: ์ธํ„ฐํŽ˜์ด์Šค ๋„์ž…๊ณผ ์˜์กด์„ฑ ์ฃผ์ž…)

    package collection.test;
    
    import collection.list.MyList;
    
    public class BatchProcessorV3 {
    
        /*
        MyArrayList์™€ MyLinkedList์˜ ์ƒ์œ„ ํƒ€์ž…์ธ MyList๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ (์ถ”์ƒ์ ์ธ ์ธํ„ฐํŽ˜์ด์Šค์— ์˜์กด)
        ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด์„œ ์™ธ๋ถ€์—์„œ ํ•ด๋‹น ์ธ์Šคํ„ด์Šค๋ฅผ ์ฃผ์ž…๋ฐ›์Œ
        MyArrayList์™€ MyLinkedList๋Š” ๋‘˜ ๋‹ค MyList๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ์–ด์„œ ์•„๋ž˜์ฒ˜๋Ÿผ MyListํƒ€์ž…์œผ๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ์Œ
        MyList = new MyArrayList;
        MyList = new MyLinkedList;
        ๊ทธ๋Ÿฌ๋ฉด ์ด ์ฝ”๋“œ์˜ ํ•„๋“œ ๋ถ€๋ถ„์€ ์ „ํ˜€ ๊ณ ์น ๊ฒŒ ์—†๊ณ  ์‚ฌ์šฉํ•˜๋Š” ์ชฝ์—์„œ ์ƒ์„ฑ์ž์—์„œ MyArrayList๋‚˜ MyLinkedList๋งŒ ๋งŒ๋“ค์–ด์„œ ๋„ฃ์–ด์ฃผ๋ฉด ๋จ
        ๋˜ ์ถ”๊ฐ€๋กœ MyList๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋‹ค๋ฅธ ์ž๋ฃŒ๊ตฌ์กฐ๊ฐ€ ํ•„์š”ํ•˜๋ฉด MyList๋ฅผ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค๋งŒ ์ถ”๊ฐ€ํ•ด์„œ ์™ธ๋ถ€์—์„œ ์ƒ์„ฑ์ž๋กœ ๋„ฃ์–ด์ฃผ๋ฉด ๋๋‚œ๋‹ค.
        ์ด ์ฝ”๋“œ๋ฅผ ๋ณด๋‹ˆ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์Šคํ”„๋ง์˜ ์ƒ์„ฑ์ž ์˜์กด์„ฑ ์ฃผ์ž…์ด ์—ฐ์ƒ๋˜์—ˆ๋‹ค.
        */
        private final MyList<Integer> list;
        
        public BatchProcessorV3(MyList<Integer> list) {
            this.list = list;
        }
        //์—„์ฒญ ๋ณต์žกํ•œ ๋กœ์ง์ด๋ผ๊ณ  ๊ฐ€์ •
        public void logic(int size) {
            long startTime = System.currentTimeMillis();
            for (int i = 0; i < size; i++) {
                list.add(0, i);
            }
            long endTime = System.currentTimeMillis();
            System.out.println("ํฌ๊ธฐ: " + size + ", ๊ณ„์‚ฐ์‹œ๊ฐ„: " + (endTime - startTime) + "ms");
        }
    }

    MyList

    package collection.list;
    
    public interface MyList<E> {
    
        int size();
        void add(E e);
        void add(int index, E e);
        E get(int index);
        E set(int index, E e);
        E remove(int index);
        int indexOf(E e);
    }

    MyArrayList

    package collection.list;
    
    import java.util.Arrays;
    
    public class MyArrayList<E> implements MyList<E> {
    
        private static final int DEFAULT_CAPACITY = 5;
    
        private Object[] elementData;
        private int size = 0;
    
        public MyArrayList() {
            elementData = new Object[DEFAULT_CAPACITY];
        }
    
        public MyArrayList(int initialCapacity) {
            elementData = new Object[initialCapacity];
        }
    
        @Override
        public int size() {
            return size;
        }
        //...์ƒ๋žต
    }

    MyLinkedList

    package collection.list;
    
    public class MyLinkedList<E> implements MyList<E> {
    
        private Node<E> first;
        private int size = 0;
    
        @Override
        public void add(E e) {
            Node<E> newNode = new Node<>(e);
            if(first == null) {
                first = newNode;
            } else {
                Node<E> lastNode = getLastNode();
                lastNode.next = newNode;
            }
            size++;
        }
        //...์ƒ๋žต
    }

    ๋ถ€๋ชจ ํƒ€์ž…์ด ์ž์‹ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋Š” ๋‹คํ˜•์„ฑ๊ณผ ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ์ปดํŒŒ์ผ ์‹œ์ ์— ์ง€์ •ํ•˜๋Š” ์ œ๋„ค๋ฆญ์„ ํ™œ์šฉํ•จ์œผ๋กœ์จ, ์ฝ”๋“œ๋Š” ๋” ์œ ์—ฐํ•˜๊ณ  ํ™•์žฅ ๊ฐ€๋Šฅํ•ด์กŒ์œผ๋ฉฐ, OCP ์›์น™์„ ์ค€์ˆ˜ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

    ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ

    package collection.test;
    
    import collection.list.MyArrayList;
    import collection.list.MyLinkedList;
    import collection.list.MyList;
    
    public class BatchProcessorMain {
    
        public static void main(String[] args) {
            //MyArrayList๋ฅผ ์‚ฌ์šฉ, ์ƒ์œ„ํƒ€์ž…์œผ๋กœ ๋ฐ›์Œ
            MyList<Integer> myArrayList =  new MyArrayList<>();
            BatchProcessorV3 processor1 = new BatchProcessorV3(myArrayList);
            //ArrayList๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ๋Š” ๊ฑด ๋น ๋ฅด์ง€๋งŒ ๋„ฃ๊ณ  ๋‚˜์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฏธ๋Š” ์—ฐ์‚ฐ์ด ํ•„์š”ํ•˜๋‹ˆ๊นŒ ๋А๋ฆฌ๋‹ค.
            //9๋งŒ๊ฑด
            processor1.logic(90_000);  // ๊ฒฐ๊ณผ: 5969ms
    
            //MyLinkedList๋ฅผ ์‚ฌ์šฉ, ์ƒ์œ„ํƒ€์ž…์œผ๋กœ ๋ฐ›์Œ
            MyList<Integer> myLinkedList =  new MyLinkedList<>();
            BatchProcessorV3 processor2 = new BatchProcessorV3(myLinkedList);
            //LinkedList๋‹ˆ๊นŒ ์•ž์— ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ๋Š” ๊ฒฝ์šฐ๋Š” ์ฐธ์กฐ๊ฐ’๋งŒ ๋ณ€๊ฒฝํ•˜๋ฉด ๋˜๊ณ  ์‹ค์ œ ๋ฐ์ดํ„ฐ์˜ ์ •๋ ฌ์€ ์—†์œผ๋‹ˆ๊นŒ ์†๋„๊ฐ€ ArrayList์— ๋น„ํ•ด์„œ ํ›จ์”ฌ ๋น ๋ฅด๋‹ค.
            //9๋งŒ๊ฑด
            processor2.logic(90_000);   // ๊ฒฐ๊ณผ: 3ms
        }
    }

    ์ด์ œ ๋‹ค๋ฅธ ๋ฆฌ์ŠคํŠธํ˜•ํƒœ์˜ ๋‹ค๋ฅธ ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด MyList๋ฅผ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ๋ฉ”์„œ๋“œ ์˜ค๋ฒ„๋ผ์ด๋“œํ•ด์„œ ์™ธ๋ถ€์—์„œ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์ธ์Šคํ„ด์Šค๋ฅผ ๋„ฃ์–ด์ฃผ๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค.(๋ฐฐ์น˜ ํ”„๋กœ๊ทธ๋žจ์€ ์ „ํ˜€ ์ˆ˜์ •ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.)


    reference: https://www.inflearn.com/course/%EA%B9%80%EC%98%81%ED%95%9C%EC%9D%98-%EC%8B%A4%EC%A0%84-%EC%9E%90%EB%B0%94-%EC%A4%91%EA%B8%89-2/dashboard?inst=e57a2bad

     

    ๊น€์˜ํ•œ์˜ ์‹ค์ „ ์ž๋ฐ” - ์ค‘๊ธ‰ 2ํŽธ ๊ฐ•์˜ | ๊น€์˜ํ•œ - ์ธํ”„๋Ÿฐ

    ๊น€์˜ํ•œ | ์ž๋ฐ” ์ œ๋„ค๋ฆญ๊ณผ ์ปฌ๋ ‰์…˜ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‹ค๋ฌด ์ค‘์‹ฌ์œผ๋กœ ๊นŠ์ด์žˆ๊ฒŒ ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค. ์ž๋ฃŒ ๊ตฌ์กฐ์— ๋Œ€ํ•œ ๊ธฐ๋ณธ๊ธฐ๋„ ํ•จ๊ป˜ ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค., ๊ตญ๋‚ด ๊ฐœ๋ฐœ ๋ถ„์•ผ ๋ˆ„์  ์ˆ˜๊ฐ•์ƒ 1์œ„, ์ œ๋Œ€๋กœ ๋งŒ๋“  ๊น€์˜ํ•œ์˜ ์‹ค์ „

    www.inflearn.com


    ๊ฐœ์ธ ์Šคํ„ฐ๋”” ๊ธฐ๋ก์„ ๋ฉ”๋ชจํ•˜๋Š” ๊ณต๊ฐ„์ด๋ผ ํ‹€๋ฆฐ์ ์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ํ‹€๋ฆฐ ์  ์žˆ์„ ๊ฒฝ์šฐ ๋Œ“๊ธ€ ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

    ๋Œ“๊ธ€