[JAVA] chapter 7. 제네릭과 컬렉션

walnut_mr·2024년 12월 27일

JAVA

목록 보기
7/11
  • 7장 - 제네릭과 컬렉션
    • 컬렉션 (collection) - 배열 (고정 크기) 단점 극복한 가변 크기 container 객체 삽입, 삭제, 검색 가능 - 배열 (고정 크기) 삽입, 삭제 시 매번 변경 필요
      // collection 주요 특징
      1. generic 기법 <E>, <V>, <K> - 타입 매개변수 (generic type)
      		Vector<Integer> // Integer 객체만
      2. collection 요소 = only 객체
      		int, char, double, boolean 등 기본 type 불가
      		Vector<int> v = new Vector<int>(); // error
      		Vector<Integer> v = new Vector<Integer>(); // O
      		
      		// 단. 삽입은 기본 타입으로 가능 (자동 boxing)
      		v.add(3); // int 타입 -> Integer 자동 boxing
      // colletction class (개발자 바로 사용 가능)
      Collection<E> // 상위 클래스 (아래 모두 Collection<E> 상속 받음)
      
      Vector<E> // 배열
      ArrayList<E>
      LikedList<E> // 연결 리스트
      Stack<E> // 스택
      HashSet<E> // 집합 (set)
    • 제네릭 (generic) - 모든 타입 다룰 수 있도록 타입 매개변수 이용 선언 C++ 템플릿과 동일
      // 제네릭 타입 매개변수
      // <E> : element - 컬렉션 요소
      // <T> : type
      // <V> : value
      // <K> : key
      
      class Stack<E> {
      		...
      		void push(E element) { ... }
      		E pop() { ... }
      }
      
      // E -> Integer : Integer 객체만 다루는 stack (구체화)
      class Stack<Integer> {
      		...
      		void push(Integer element) { ... }
      		Integer pop() { ... }
      }
    • 제네릭 컬렉션 활용
      1. Vector - 자동 크기 x 2

        synchronized (동기화) & thread-safe → multi thread에서 유리

        // Vector<E> - 배열 가변 크기 (자동 크기 조절, 자리 이동)
        // full -> 자동으로 크기 x 2
        Vector<Integer> v = new Vector<Integer>();
        Vector v = new Vector(); // type 지정 안 할 시, 경고
        
        // 활용법 (null 도 삽입 가능)
        Vector<Integer> v = new Vector<Integer>(7); // 크기 7 지정
        v.add(Integer.valueOf(5)); // v.add(5) 와 동일
        v.add(5); // 맨 뒤에 자동 삽입 (자동 boxing)
        v.add(4);
        v.add(-1); // 5 4 -1 순
        
        int n = v.size(); // size : 사용 중인 크기 = 3
        int c = v.capacity(); // capacity : 전체 배열 크기 = 7
        
        v.add(2, 100); // 5 4 100 -1 (index 2에 100 삽입)
        v.add(3, null); // 5 4 100 null -1 (null 삽입 가능)
        v.add(5, 100); // error - v.size() 보다 큰 곳에 삽입 불가
        
        Integer obj = v.get(1); // Integer 타입의 객체 (4) 가져옴
        int i = obj.intValue(); // i = 4
        int j = v.get(1); // j = 4, (자동 unboxing)
        
        v.remove(1); // index 1의 요소 삭제 - 5 100 null -1 (index 삭제)
        Integer m = Integer.valueOf(100);
        v.remove(m); // 레퍼런스 이용 삭제 - 5 null -1 (레퍼런스 삭제)
        
        int last = v.lastElement(); // 마지막 요소
        v.removeAllElements(); // 모두 삭제 & 크기 0
        v.clear(); // 모두 삭제
        import java.util.*;
        
        public class VectorEx {
        		public static void printVector(Vector<Integer> v) {
        				for (int i = 0; i < v.size(); i++)
        						System.out.println(v.get(i)); // 자동 unboxing
        		}
        		public static void main(String[] args) {
        				Vector<Integer> v = new Vector<Integer>(); // Java 7 이전
        				Vector<Integer> v = new Vector<>(); // Java 7 이후 (추론)
        				var v = new Vector<Integer>(); // Java 10 이후 (var 사용)
        				
        				v.add(5);
        				v.add(3);
        				v.add(1, 100);
        				
        				printVector(v); // 5 100 3 출력
        		}
        }
      2. ArrayList - vector와 달리 thread 자동 동기화 X (크기 50% 증가)

        asychronous (비동기) & not thread-safe → single thread에 유리

        safety checking 없어서 vector보다 빠름 / 크기 50%씩 증가

        import java.util.*;
        
        ArrayList<String> al = new ArratList<String>();
        al.add("Hello");
        al.add("Hi");
        al.add("Java"); // Hello Hi Java
        
        int n = al.size(); // n = 3
        int c = al.capacity(); // error - ArrayList는 capacity 없음
        
        al.add(2, "Sahni"); // Hello Hi Sahni Java
        String str = al.get(1); // str = "Hi"
        al.remove(1); // Hello Sahni Java
        al.remove("Sahni"); // Hello Java
        al.clear();
      3. Iterator - 순차 검색을 위한 interface - hasNext(), next(), remove()

        // Iterator<E> : <E>에는 컬렉션과 동일한 타입 매개변수
        // 주요 method
        boolean hasNext() // 다음 요소 존재 - true
        E next() // 다음 요소 return
        void remove() // 마지막 return 요소 제거
        
        Vector<Integer> v = new Vector<Integer>();
        Iterator<Integer> it = v.iterator(); // iterator interface 선언
        
        int sum = 0;
        
        // v.size() 로 순회
        for (int i = 0; i < v.size(); i++)
        		sum += v.get(i);
        
        // iterator로 순회
        while(it.hasNext()) {
        		int n = it.next();
        		sum += n;
        }
        
        it = v.iterator(); // 처음으로 지정해주려면 선언 다시 해야됨
      4. HashMap<K, V> - key (data type), value (type 매개변수) put()

        장점 : 요소 삽입, 삭제, 검색 매우 빠름 / 단점 : key로만 접근 가능

        // 주요 method
        void clear() // 모든 요소 삭제
        boolean containsKey(Object key) // key값 갖고 있으면 true
        boolean containsValue(Object value) // value 갖고 있으면 true
        V get(Object key) // key에 대한 value 리턴
        Set<K> keySet() // 모든 key 담은 Set<K> 컬렉션 return
        V put(K key, V value) // 저장 (key, value)
        V remove(K key) // key, value 쌍 모두 삭제
        int size() // HashMap size
        import java.util.*;
        
        public class HashMapEx {
        		public static void main(String[] args) {
        				HashMap<String, String> dic = new HashMap<String, String>();
        				
        				dic.put("baby", "아기"); // 삽입
        				dic.put("love", "사랑");
        				dic.put("apple", "사과");
        				
        				Set<String> keys = dic.keySet(); // key 집합
        				Iterator<String> it = keys.iterator(); // iterator 선언
        				
        				while(it.hasNext()) { // dic 모두 출력
        						String word = it.next();
        						System.out.println("(" + word + ", " + dic.get(word) + ")");
        				}
        				
        				Scanner scanner = new Scanner(System.in);
        				while(true) {
        						System.out.print("찾고 싶은 단어 : ");
        						String eng = scanner.next();
        						if (eng.equals("exit")) {
        								System.out.println("시스템 종료");
        								break;
        						}
        						String kor = dic.get(eng); // 검색
        						if (kor == null)
        								System.out.println("사전에 없는 단어");
        						else
        								System.out.println(kor);
        				}
        				scanner.close();
        		}
        }
      5. LinkedList - 양방향 연결 관리 - head, tail

        head, tail 레퍼런스 통해 맨 뒤, 맨 앞 접근 가능 (stack, queue로 활용)

      6. Collections 클래스 - static : 생성자 필요 없음

        정렬 (sort), 반대로 (reverse), 최대 최소(max, min), 이진 탐색 (binarySearch())

        import java.util.*;
        
        public class CollectionEx {
        		static void printList(LinkedList<String> l) {
        				Iterator<String> it = l.iterator();
        				while (it.hasNext()) {
        						String e = iterator.next();
        						String separator;
        						if (iterator.hasNext())
        								separator = "->";
        						else
        								separator = "\n";
        						System.out,print(e + separator);
        				}
        		}
        		public static void main(String[] args) {
        				LinkedList<String> l = new LinkedList<String>();
        				l.add("트랜스포머");
        				l.add("스타워즈");
        				l.add("매트릭스");
        				l.add(0, "터미네이터");
        				l.add(2, "아바타"); // 터 트 아 스 매
        				
        				Collections.sort(l); // 가나다 순 정렬
        				printList(l); // 매->스->아->터->트
        				
        				Collections.reverse(l); // 역순
        				printList(l); // 트->터->아->스->매
        				
        				int index = Collections.binarySearch(l, "아바타") + 1;
        				System.out.println("아바타는" + index + "번째 요소"); // 3
        		}
        }
    • 제네릭 만들기 - 일반 타입 매개변수 지정
      // 제네릭 클래스 작성
      public class MyClass<T> {
      		T val; // 변수 val의 타입은 T
      		void set(T a) {
      				val = a;
      		}
      		T get() {
      				return val;
      		}
      }
      
      // 제네릭 클래스에 대한 레퍼런스 선언
      MyString<String> s;
      List<Integer> li;
      Vector<String> vs;
      
      // 구체화
      MyClass<String> s = new MyClass<String>(); // String으로 지정
      s.set("hello");
      System.out.println(s.get()); // hello 출력
      
      MyClass<Integer> i = new MyClass<Integer>(); // Integer로 지정
      i.set(10); // 자동 boxing
      System.out.println(i.get()); // 10 출력
      제네릭 타입 가진 객체 생성 불가 - 아래 error 코드
      // error code
      public class MyVector<E> {
      		E create() {
      				E a = new E(); // error - 타입 E를 모르기 때문
      				return a;
      		}
      }
      // Generic Stack 생성
      class GStack<T> {
      		int tos;
      		Object[] stck; // 배열
      		public GStack() { // 생성자
      				tos = 0;
      				stck = new Object[10]; // 10칸 배열 생성
      				stck = new T[10]; // error - 제네릭 타입 불가
      		}
      		public void push(T item) {
      				if (tos == 10) // full
      						return;
      				stck[tos] = item;
      				tos++;
      		}
      		public T pop() {
      				if (tos == 0) // empty
      						return null;
      				tos--;
      				return (T)stck[tos]; // 타입 매개변수 type으로 캐스팅
      				// stck = Object[10]; 으로 Object 타입으로 선언했으므로 강제 캐스팅 필요
      		}
      }
      
      public class MyStack {
      		public static void main(String[] args) {
      				GStack<String> stringStack = new GStack<String>(); // String Stack
      				
      				stringStack.push("seoul");
      				stringStack.push("busan");
      				stringStack.push("LA");
      				
      				for (int i = 0; i < 3; i++)
      						System.out.println(stringStack.pop()); // La busan seoul
      						
      				GStack<Integer> intStack = new GStack<Integer>(); // Integer Stack
      				
      				intStack.push(1);
      				intStack.push(3);
      				intStack.push(5);
      				
      				for (int i = 0; i < 3; i++)
      						System.out.println(intStack.pop()); // 5 3 1
      		}
      }
      
      // 제네릭과 배열 - 제네릭 클래스, 인터페이스 타입 배열 불가
      GStack<Integer>[] intStack = new GStack<Integer>[10]; // error
      T[] a = new T[10]; // error
      public void myArray(T[] a) { ... } // 레퍼런스로는 가능
      
      // 제네릭 method
      class GenericMethodEx {
      		static <T> void toStack(T[] a, GStack<T> gs) { // T가 타입 매개변수인 제네릭 메소드
      				for (int i = 0; i < a.length; i++)
      						gs.push(a[i]);
      		}
      }
      // 제네릭 장점
      1. compile시 type 구체화 -> 안전한 프로그래밍 가능
      2. runtime 타입 충돌 방지
      3. 타입 캐스팅 불필요
      4. ClassException 방지
profile
https://github.com/khkim09

0개의 댓글