열심히 끝까지

Java2 day12 본문

Java2(주말)

Java2 day12

노유림 2022. 5. 15. 22:48

[12일차 수업내용]
Collection Framework( 컬렉션 프레임워크 )
            - ArrayList, LinkedList
            - Iterator
            - Stack, Queue

===================================================================
1. 컬렉션프레임워크 ( Collection Framework )
            - 컬렉션프레임워크란, '데이터군을 저장하는 클래스들을 표준화한 설계'를 뜻함
            - 컬렉션은 다수의 데이터, 즉 데이터 그룹을 의미하고 
              프레임워크 표준화된 프로그래밍 방식을 의미
            - 컬렉션프레임워크는 컬렉션, 다수의 데이터를 다루는데에 필요한 
              다양하고 풍부한 클래스들을 제공하기 때문에
              프로그래머의 짐을 상당히 덜어주고 있으며, 
              또한 인터페이스의 다형성을 이용한 객체지향적 설계를 통해
              표준화되어 있기 때문에 사용법을 익히기에도 편리하고 
              재사용성이 높은 코드를 작성할 수 있다는 장점이 있음

            1-1 ) 컬렉션프레임워크의 핵심 인터페이스
                        - 컬렉션프레임워크에서는 컬렉션 데이터 그룹을 3가지 타입이 존재한다고 인식하고
                          각 컬렉션을 다루는데 필요한 기능을 가진 3개의 인터페이스를 정의
                          ( List, Set, Map )
                        - 인터페이스 List와 Set의 공통된 부분을 뽑아 새로운 인터페이스인 
                          Collection 인터페이스가 추가로 정의
                        - 인터페이스 List와 Set을 구현한 컬렉션 클래스들은 서로 많은 공통부분이 있어서
                          공통된 부분을 다시 뽑아 Collection인터페이스로 정의할 수 있었지만
                          Map 인터페이스는 이들과 전혀 다른 형태로 컬렉션을 다루기 때문에
                          상속계층도에 포함되지 못함

                        인터페이스                                                   특징
                        
                        List                                   순서가 있는 데이터의 집합(index), 데이터의 중복 허용
                                                               구현한 클래스 : ArrayList, LinkedList, Stack, Vector

                        Set                                   순서를 유지하지 않는 데이터의 집합(index X)
                                                               데이터의 중복 허용 불가
                                                               구현한 클래스 : HashSet, TreeSet

                        Map                                  {apple : "사과"}(apple = key, "사과" = value)
                                                               키(key)와 값(value)의 쌍으로 이루어진 데이터의 집합
                                                               순서는 유지되지 않으며, 키는 중복을 허용하지 않고
                                                               값은 중복을 허용
                                                               구현한 클래스 : HashMap, TreeMap, HashTable, Properties ...

                        - 실제 개발시에는 다루고자 하는 컬렉션의 특징을 파악하고 어떤 인터페이스를 

                          구현한 컬렉션 클래스를 사용해야 하는지 결정해야 하므로 위의 

                          인터페이스의 특징과 차이를 잘 이해하고 있어야 함
                        - 컬렉션프레임워크의 모든 컬렉션 클래스들은 List, Set, Map 중의 하나를 구현하고 있으며,
                          구현한 인터페이스의 이름이 클래스 이름에 포함되어 있어서 이름만으로도 클래스의 특징을
                          쉽게 알 수 있도록 되어있음

                        ①  Collection Interface
                                    - List와 Set의 조상인 Collection인터페이스에는 다음과 같은 메소드들이 정의되어 있음
                                    - Collection 인터페이스는 컬렉션클래스에 저장된 데이터 읽고, 추가하고 삭제하는 등
                                      컬렉션을 다루는데 가장 기본적인 메소드들을 정의하고 있음
                         
                        ② List  Interface
                                    - List 인터페이스는 중복을 허용하면서 저장순서가 유지되는 컬렉션을 

                                      구현하는데 사용

                        ③ Set Interface
                                    - Set 인터페이스는 중복을 허용하지 않고 저장 순서가 유지되지 않는 

                                      컬렉션을 구현하는데 사용

                        ④ Map Interface
                                    - Map 인터페이스는 키(key), 값(value)을 하나의 쌍으로 묶어서 저장하는 컬렉션 클래스를
                                      구현하는데 사용
                                    - 키(key)는 중복될 수 없지만 값(value)은 중복을 허용
                                    - 기존에 저장된 데이터와 중복된 키와 값을 저장하면 
                                      기존의 값은 없어지고 마지막에 저장된 값만 남음

            1-2 ) List Interface
                        ① ArrayList
                                    - ArrayList는 컬렉션프레임워크에서 가장 많이 사용되는 컬렉션클래스일 것
                                    - 이 ArrayList는 List인터페이스를 구현하기 때문에 
                                      저장순서가 유지되고, 중복을 허용한다는 특징이 있음
                                    - ArrayList는 기존의 Vector클래스를 개선한 것으로 
                                      Vector의 구현원리와 기능적인 측면에서는 동일하다고 볼 수 있음
                                    - ArrayList는 Object배열을 이용해서 데이터를 순차적으로 저장
                                    - 만약 배열에 더 이상 저장할 공간이 없으면 보다 큰 새로운 배열을 생성해서
                                      기존의 배열에 저장된 내용을 새로운 배열로 복사한 다음에 저장
                                    
                                    *배열의 단점
                                    - 배열을 가장 기본적인 형태의 자료구조구조가 간단하며 사용하기 쉽고
                                      데이터를 읽어오는데 걸리는 시간(접근시간 : access time)이 가장 빠르다는 

                                      장점을 가지고 있지만 다음과 같은 단점을 가지고 있음
                                    
                                    1) 크기를 변경할 수 없음
                                                - 크기를 변경할 수 없으므로  새로운 배열을 생성해서 복사해야 함
                                                - 실행속도를 향상시키기 위해 충분히 큰 배열을 생성할 순 있으나
                                                  메모리의 낭비가 발생
                                    2) 비순차적인 데이터의 추가, 삭제에 시간이 많이 걸림
                                                - 차례대로 데이터를 추가하고 마지막에서부터 데이터를 삭제하는건 빠름
                                                - 단, 배열의 중간에 데이터를 추가 혹은 삭제하려면 
                                                  빈자리를 만들기 위해서 데이터를 복사해서 이동해야 함

                        ② LinkedList
                                    - 위와 같은 배열의 단점을 보완하기 위해 LinkedList라는 자료구조가 고안
                                    - 배열은 모든 데이터가 연속적으로 존재하지만 LinkedList는 불연속적으로 

                                      전재하는 데이터들을 서로 연결한 상태로 구성
                                    - LinkedList에서의 데이터삭제는 간단
                                    - 삭제하고자하는 요소의 이전요소가 삭제하고자하는 요소의 
                                      다음 요소를 참조하도록 변경하기만 하면 됨
                                                ==> 배열처럼 데이터를 이동하는 복사과정이 없기 때문에 

                                                       처리속도가 굉장히 빠름
                                    - LinkList역시 List 인터페이스를 구현했기 때문에 ArrayList와 내부 구현방법만 다를 뿐
                                      메소드의 종류와 기능은 거의 같음
                                    
                        ③ ArrayList Vs LinkedList

                        컬렉션            읽기(접근시간)            추가/삭제                        비고
                        ArrayList          빠르다                      느리다              순차적인 추가/삭제는 빠름
                                                                                                 비효율적인 메모리 사용 가능성이 높음
                        LinkedList        느리다                       빠르다          데이터가 많으면 많을수록 접근성이 떨어짐

                        * 결론 *
                                    - 다루고자 하는 데이터의 개수가 변하지 않는 경우라면 ArrayList가 

                                      최상의 선택이 되겠지만, 데이터의 변경이 잦다면 LinkedList를 사용하는 것이 

                                      더 나은 선택이 될 것
                                    - 두 클래스의 장점을 이용해서 두 클래스를 조합해서 사용하는 방법도 생각해 볼 수 있음 
                                    ==> 처음에 작업하기 전에 데이터를 저장할 때는 ArrayList를 사용한 다음,
                                           중간에 작업할 때 LinkedList로 데이터를 옮겨서 작업하면 좋은 효율을 

                                           얻을 수 있을 것

                        ④ 스택과 큐( Stack & Queue )
                                    - Stack은 마지막에 저장된 데이터를 가장 먼저 꺼내는 

                                      LIFO(후입선출 : Last In First Out) 구조로 되어있고
                                      Queue는 처음에 저장된 데이터를 가장 먼저 꺼내는 

                                      FIFO(선입선출 : First In First Out) 구조로 되어 있음
                                    - Stack을 구현할 때 ArrayList와 같은 배열 기반의 컬렉션 클래스가 적합하지만,
                                      Queue는 데이터를 꺼낼 때 항상 첫번째 데이터를 삭제하므로 

                                      LinkedList로 구현하는 것이 더 좋음

                                    Stack Ex)            수식괄호검사, 웹브라우저의 뒤로/앞으로 가기 기능 등
                                    Queue Ex)           최근 사용 문서, 인쇄작업 대기 목록 등

                                    Stack ==> ArrayList
                                    Queue ==> LinkedList


------------------------------------------------------------------------------------------------

package arrayList;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;

 

public class ArrayListEx {
            public static void main(String[] args) {
                        ArrayList list = new ArrayList();

                        // boolean add(Object e) : ArrayList의 마지막에 객체를 추가
                        // 성공하면 true, 실패하면 false를 반환
                        list.add(1); // Object e = 1; auto boxing wrapper이용

                        list.add(Integer.valueOf(2));
                        list.add(new Integer(5));
                        list.add(0);
                        list.add(3);
                        list.add(1);

                        System.out.println("list : " + list);
                        System.out.println();


                        // Object get(int index) : 지정된 위치에 저장된 객체를 반환한다.
                        int result = (int)list.get(3);
                        System.out.println("result : " + result);
                        System.out.println();

 

                        // int size() : ArrayList에 저장된 객체의 수를 반환한다.
                        for(int i = 0; i < list.size(); i++) {
                             System.out.print(list.get(i) + " ");
                         }
                         System.out.println();
                         System.out.println();
    
                         // List subList(int fromIndex, int toIndex) 
                         //      ==> formIndex부터 toIndex 사이에 저장된 객체를 반환한다.
                        List list2 = list.subList(1, 4);
                        System.out.println("list2 : " + list2);
    
                        // ArrayList(Collection c);
                        ArrayList list3 = new ArrayList(list2);
                        System.out.println("list3 : " + list3);
    
                        LinkedList datas = new LinkedList();
    
                        new LinkedList(datas); // 다형성
                        new ArrayList(new HashSet());
                        new ArrayList(new LinkedList());
    
                        /*
                        * boolean containAll(Collection c)
                        * boolean contains(Object o)
                        *      지정된 객체 또는 Collection의 객체들이 Collection에 포함되어 있는지 확인한다.
                        */
                        // list : [1,2,5,0,3,1]       list3 : [2,5,0]
                        System.out.println("list.contains(4) : " + list.contains(4)); // false
                        System.out.println("list.contains(list3) : " + list.contains(list3)); // true
                        System.out.println();
    
                        // Object set(int index, Object element) : 주어진 객체를 지정된 위치에 저장한다.
                        list3.add("B");
                        list3.add("C");
                        list3.add(3, "A"); // 값을 추가
                        // list : [1,2,5,0,3,1]       list3 : [2,5,0,A,B,C]
                        System.out.println("list3 : " + list3);
                        list3.set(3, "AA"); // 값을 변경
                        System.out.println("list3 : " + list3);
                        System.out.println();
    
                        /*
                        * boolean retainAll(Collection c)
                        *     지정된 Collection에 포함된 객체만을 남기고 다른 객체들은 Collection에서 삭제한다.
                        *     이 작업으로 인해 Collection에 변화가 있으면 true, 그렇지 않으면 false를 반환한다.
                        */
                        // list : [1,2,5,0,3,1]     list3 : [2,5,0,AA,B,C]
                        System.out.println("list.retainAll(list3) : " + list.retainAll(list3));
                        System.out.println("list : " + list);
                        System.out.println("list3 : " + list3);
                        System.out.println();
    
                        /*
                        * boolean remove(Object o)   : 지정된 객체를 삭제한다.
                        * Object remove(int index)   : 해당 인덱스의 객체를 삭제한다.
                        */
                        // list : [2, 5, 0]
                        list.remove(2); // Object remove(int index)
                        System.out.println("list : " + list); // list : [2,5]
                        list.remove(Integer.valueOf(2)); // boolean remove(Object o)
                        System.out.println("list : " + list); // list : [5]
            }
}

--------------------------------------------------------------------------------
package linkedList;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class ArrayListLinkedListEx01 {
            public static void main(String[] args) {
                        ArrayList al = new ArrayList();
                        LinkedList ll = new LinkedList();

                        System.out.println("= 순차적으로 추가하기 =");
                        System.out.println("ArrayList : " + add1(al));
                        System.out.println("LinkedList : " + add1(ll));
                        System.out.println();
                        System.out.println("= 중간에 추가하기 =");
                        System.out.println("ArrayList : " + add2(al));
                        System.out.println("LinkedList : " + add2(ll));
                        System.out.println();
                        System.out.println("= 중간에 삭제하기 =");
                        System.out.println("ArrayList : " + remove2(al));            
                        System.out.println("LinkedList : " + remove2(ll));
                        System.out.println();
                        System.out.println("= 순차적으로 삭제하기 = ");
                        System.out.println("ArrayList : " + remove1(al));
                        System.out.println("LinkedList : " + remove1(ll));
            }

            // Step 1 : 순차적으로 추가하는 메소드
            public static long add1(List list) {
                        long start = System.currentTimeMillis();

                        for(int i = 0; i < 1000000; i++) {
                                    list.add(i + "");
                        }

                        long end = System.currentTimeMillis();

                        return end - start;
            }

            // Step 2 : 비순차적으로 추가하는 메소드
            public static long add2(List list) {
                        long start = System.currentTimeMillis();

                        for(int i = 0; i < 10000; i++) {
                                    list.add(500, "X");
                        }

                        long end = System.currentTimeMillis();

                        return end - start;
            }

             // Step 3 : 순차적으로 삭제하는 메소드
            public static long remove1(List list) {
                        long start = System.currentTimeMillis();

                        for(int i = list.size()-1; i >= 0; i--) {
                                    list.remove(i);
                        }

                        long end = System.currentTimeMillis();

                        return end - start;
            }
            // Step 4 : 비순차적으로 삭제하는 메소드
            public static long remove2(List list) {
                        long start = System.currentTimeMillis();

                        for(int i = 0; i < 10000; i++) {
                                    list.remove(i);
                        }

                        long end = System.currentTimeMillis();

                        return end - start;
            }
}

-------------------------------------------------------------------------------
package linkedList;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class ArrayListLinkedListEx02 {
            public static void main(String[] args) {
                        ArrayList al = new ArrayList();
                        LinkedList ll = new LinkedList();
                        add(al);
                        add(ll);

                        System.out.println("= 접근시간 테스트 =");
                        System.out.println("ArrayList : " + access(al));
                        System.out.println("LinkedList : " + access(ll));
            }

            // Step 1 : 순차적인 데이터 추가
            public static void add(List list) {
                        for(int i = 0; i < 100000; i++) {
                                    list.add(i + "");
                        }
            }

            // Step2 : 데이터 접근시간(access time) 테스트
            public static long access(List list) {
                        long start = System.currentTimeMillis();

                        for(int i = 0; i < 100000; i++) {
                                    list.get(i);
                        }

                        long end = System.currentTimeMillis();

                        return end - start;
            }
}

---------------------------------------------------------------
package stackandqueue;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

public class StackQueueEx {
            public static void main(String[] args) {
                        Stack stack = new Stack();
                        Queue queue = new LinkedList();
                        // Queue 인터페이스의 구현체인 LinkedList를 사용한다.
                        stack.push("0");
                        stack.push("1");
                        stack.push("2");
                        System.out.println("= peek() 수행 전 stack =");
                        System.out.println("stack : " + stack);
                        System.out.println(stack.peek());
                        System.out.println("= peek() 수행 후 stack =");
                        System.out.println("stack : " + stack);
                        System.out.println();

                        System.out.println("=====================");
                        System.out.println("= pop() 수행 전 stack =");
                        System.out.println("stack : " + stack);
                        System.out.println(stack.pop());
                        System.out.println("= pop() 수행 후 stack =");
                        System.out.println("stack : " + stack);

                        System.out.println("#####################################");
                        queue.offer("0");
                        queue.offer("1");
                        queue.offer("2");

                        System.out.println("= peek() 수행 전 queue =");
                        System.out.println("queue : " + queue);
                        System.out.println(queue.peek());
                        System.out.println("= peek() 수행 후 queue =");
                        System.out.println("queue : " + queue);
                        System.out.println();

                        System.out.println("=====================");
                        System.out.println("= poll() 수행 전 queue =");
                        System.out.println("queue : " + queue);
                        System.out.println(queue.poll());
                        System.out.println("= poll() 수행 후 queue =");
                        System.out.println("queue : " + queue);

                        System.out.println("#####################################");
                        System.out.println("[stack]");
                        while(!stack.empty()) {
                                    stack.pop();
                        }
                        System.out.println("stack : " + stack);

                        while(!queue.isEmpty()) {
                                    queue.poll();
                        }
                        System.out.println("queue : " + queue);
            }
}

============================================================
            1-3) Enumeration, Iterator, ListIterator
                        - Enumeration, Iterator, ListIterator은 
                          모두 컬렉션 클래스에 저장된 데이터를 접근하는데 사용되는 인터페이스
                        - Enumeration는 Iterator의 구버전이며 Iterator의 접근성을 향상시킨 것은 ListIterator

                        ① Iterator
                                    - 컬렉션프레임워크에서 컬렉션에 저장된 요소들을 읽어오는 방법을 표준화하였음
                                    - 컬렉션에 저장된 각 요소에 접근하는 기능을 가진 Iterator 인터페이스를 정의하고
                                      Collection 인터페이스에는 'iterator(Iterator를 구현한 클래스의 인스턴스)'를
                                      반환하는 메소드 iterator()를 정의하고 있음
                                    - 그래서 List나 Set 인터페이스를 구현하는 컬렉션은 iterator()가 
                                      각 컬렉션의 특징에 맞게 작성되어 있음

                        ② Enumeration와 ListIterator
                                    - Enumeration은 컬렉션프레임워크가 만들어지기 이전에 사용하던 것으로 
                                      Iterator의 구버전이라고 할 수 있음
                                    - 이번버전으로 작성된 소스와의 호완을 위해 남겨두고 있을 뿐 가능하면 

                                      Iterator를 사용
                                    - ListIterator는 Iterator를 상속받아 기능을 추가한 것으로 컬렉션의 요소에 접근할 때
                                      Iterator는 단방향으로만 이동할 수 있는데에 반해 

                                      ListIterator는 양방향으로의 이동이 가능
                                    - 다만 ArrayList와 LinkedList와 같이 List인터페이스를 구현한 컬렉션에서만 
                                      ListIterator의 사용이 가능

--------------------------------------------------------------------------------------
package iterator;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

public class IteratorEx01 {
            public static void main(String[] args) {
                        // Step 1 : List인터페이스에서 iterator 사용하기
                        System.out.println("= List 인터페이스 사용 =");
                        List list = new ArrayList();
                        list.add("1");
                        list.add("2");
                        list.add("3");
                        list.add("4");
                        list.add("5");

                        // get을 이용한 데이터 접근
                        for(int i = 0; i < list.size(); i++) {
                                    System.out.print(list.get(i) + " ");
                        }
                        System.out.println();

                        // iterator를 이용한 데이터 접근
                        Iterator it = list.iterator();

                        while(it.hasNext()) {
                                    System.out.print(it.next() + " ");
                        }
                        System.out.println();
                        while(it.hasNext()) {
                                    System.out.print(it.next() + " ");
                        } // iterator는 일회성이다.
                        System.out.println();

                        it = list.iterator();
                        while(it.hasNext()) {
                                    System.out.print(it.next() + " ");
                        }
                        System.out.println();

                        System.out.println("= Set 인터페이스 사용 =");
                        Set set = new HashSet();
                        set.add("1");
                        set.add("2");
                        set.add("3");
                        set.add("4");
                        set.add("5");

                        it = set.iterator();
                        while(it.hasNext()) {
                                    System.out.print(it.next() + " ");
                        }

            }
}

----------------------------------------------------------------
package iterator;

import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;

public class IteratorEx02 {
            public static void main(String[] args) {
                        ArrayList original = new ArrayList();

                        for(int i = 0; i < 10; i++) {
                                    original.add(i + "");
                        }

                        System.out.println("original : " + original);

                        ArrayList copy = new ArrayList();

                        // iterator를 이용해서 original의 출력결과와 copy의 출력결과가 같게 하라.
                        Iterator it = original.iterator();
                        while(it.hasNext()) {
                                    copy.add(it.next());
                        }

                        System.out.println("copy : " + copy);
            }
}

'Java2(주말)' 카테고리의 다른 글

Java2 day14  (0) 2022.05.22
Java2 day13  (0) 2022.05.21
Java2 day11 보충  (0) 2022.05.15
Java2 day11  (0) 2022.05.14
Java2 day10  (0) 2022.05.09