본문 바로가기

JAVA

java #12 Collections, 지네릭스

1.Collections
1) Collections - 컬렉션을 위한 메서드(static)을 제공
a. 컬렉션 채우기, 복사, 정렬, 검색
b. 컬렉션 동기화 - synchronizedXXX()
c. 변경불가(readOnly 읽기전용) 컬렉션 만들기 - unmodifiableXXX()
d. 싱글톤 컬렉션 만들기(객체 1개만 저장) - singletonXXX()
e. 한 종류의 객체만 저장하는 컬렉션 만들기 - checkedXXX()

ex)

import java.util.*;
import static java.util.Collections.*;

public class CollectionsEx {

	public static void main(String[] args) {
		List list = new ArrayList();
		System.out.println(list);
		
		addAll(list,1,2,3,4,5);
		System.out.println(list);
		
		rotate(list, 2); // 반시계 방향으로 두번 회전
		System.out.println(list);
		
		swap(list,0,2); // 첫 번째와 세 번째를 교환
		System.out.println(list);
		
		shuffle(list); // 저장된 요소의 위치를 임의로 변경
		System.out.println(list);
		
		sort(list,reverseOrder()); // 역순 정렬 reverse(list)
		System.out.println(list);
		
		sort(list);
		System.out.println(list);
		
		int idx = binarySearch(list,3); // 바이너리 서치를 사용할 떄 정렬먼저 해야함!!
		System.out.println("index of 3 = " + idx);
		
		System.out.println("max = " +max(list));

	}

}

2. 지네릭스(Generics)란?
1) 지네릭스란?
a. 컴파일시 타입을 체크해 주는 기능(compile-time type check) - JDK1.5
ex) ArratList<Tv> tvList = new ArrayList<Tv>();
     tvList.add(new TV()); // ok
     tvList.add(new Audio()); // 컴파일 에러. TV 외에 다른 타입을 저장 불가
b. 객체의 타입 안정성을 높이고 형변환의 번거로움을 줄여줌
ex) ArrayList<Tv> tvList = new ArrayList<Tv>();
     tvList.add(new Tv());
     Tv t = tvList.get(0); // 형변환 불필요!


2) 지네릭스의 장점
a. 타입 안정성을 제공한다.
b. 타입체크와 형변환을 생략할 수 있으므로 코드가 간결해 진다.

3) 지네릭스 용어
Box<T> : 지네릭 클래스, 'T의 Box' 또는  'T Box'라고 읽는다.
T : 타입 변수 또는 타입 매개변수.(T는 타입 문자)
Box : 원시 타입 (raw type)
ex) class Box <T> // 지네릭 클래스 선언
 // Box는 원시 타입, Box<T> 는 지네릭 클래스 , <T>는 타입
ex) Box<String> b = new Box<String>(); // <String> 타입이 일치해야 함 !!


4) 지네릭 타입과 다형성
a. 참조 변수와 생성자의 대입된 타입은 일치해야 한다.
ex) ArrayList<TV> list = new ArrayList<Tv>(); // ok. 일치
     ArrayList<Product> list = new ArrayList<Tv>(); // 에러. 불일치 (타입변수 불일치)
b. 지네릭 클래스간의 다형성은 성립.(여전히 대입된 타입은 일치해야)
ex) List<Tv> list = new ArrayList<Tv>(); // ok. 다형성 ArrayList가 List를 구현
     List<Tv> list = new LinkedList<Tv>(); // ok. 다형성 LinkedList가 List를 구현
c. 매개변수의 다형성도 성립.

ex) ArrayList<Product> list = new ArrayList<Product>();
    list.add(new Product());
    list.add(new Tv()); // Product 자손이기 때문에 ok.
    list.add(new Audio()); // Product 자손이기 때문에 ok.
    boolean add (E e) { ... } -> boolean add(Product e) { ... } // 그 자손 객체도 가능함 (다형성)


5) 제한된 지네릭 클래스
a. extends로 대입할 수 있는 타입을 제한
ex) class FruitBox<T extends Fruit> {
ArrayList<T> list = new ArrayList<T>();
}
FruitBox<Apple> appleBox = new FruitBox<Apple>(); // ok
FruitBox<Toy> toyBox = new FruitBox<Toy>(); // Toy는 Fruit의 자손이 아님

 

b. 인터페이스인 경우에도 extends를 사용
ex) interface Eatable {} 
class FruitBox<T extends Eatable> {} // implements 사용 X

6) 지네릭스의 제약
a. 타입 변수에 대입은 인스턴스 별로 다르게 가능
ex) Box<Apple> appleBox = new Box<Apple>(); // Apple 객체만 저장가능
    Box<Grape> grapeBox = new Box<Grape>(); // Grape 객체만 저장가능

b. static멤버에 타입 변수 사용 불가 -> static은 모든 인스턴스에 공통
ex) class Box<T> {
static T item; // 에러
static int compare(T t1, T t2) {} // 에러

c. 배열/객체 생성할 때 타입 변수 사용 불가. 타입 변수로 배열 선언은 가능
ex) class Box<T> {
T[] itemArr; // ok. T타입의 배열을 위한 참조변수
...
T[] toArray() {
T[] tmpArr = new T[itemArr.length]; // 에러 지네릭 배열 생성불가

3. 타입 변수
1) 타입 변수란?
a. 클래스를 작성할 때, Object타입 대신 타입변수(E)를 선언해서 사용.
ex) public class ArrayList<E> extends AbstractList<E> {
private transient E[] elementData;
public boolean add(E o) {} 
public E get (int index) {}
}
2) 타입 변수에 대입하기
a. 객체를 생성시, 타입 변수(E) 대신 실제 타입(Tv)을 지정 대입
ex) ArrayList<Tv> tvList = new ArrayList<Tv>(); (타입 일치해야 됨)
b. 타입 변수 대신 실제 타입이 지정되면, 형 변환 생략가능

4. Iterator, HashMap과 지네릭스
1) Iterator<E>
a. 클래스를 작성할 때, Object타입 대신 T와 같은 타입 변수를 사용

2)HashMap<V,K>
a. 여러 개의 타입 변수가 필요한 경우, 콤마()를 구분자로 선언
ex) HashMap<String,Student> map = new HashMap<String, Student>(); // 생성
     map.put("자바왕",new Student("자바왕",1,1,100,100,100)); // 데이터 저장
public class HashMap<K,V> extends AbstractMap<K,V> { // 일부 생략
public V get(Object key) { //생략 }
public V put(K key, V value) { .. }
public V remove(Object key) { .. }
}