Chapter 13. 컬렉션과 제네릭 (3)

SeungHyun Son·2021년 7월 3일
0

Stack과 Queue

  • Stack : 후입선출(LIFO, Last In First Out) 자료구조
  • Queue : 선입선출(FIFO, First In First Out) 자료구조

Stack

LIFO 자료구조를 구현한 클래스

Stack 객체 생성

Stack<E> stack = new Stack<E>();

Stack 클래스 주요 메소드

리턴타입메소드설명
Epuch(E item)주어진 객체를 스택에 추가
Epeek()스택의 최상단(top) 객체를 가져온다. 객체를 제거하지 않음
Epop()스택의 최상단(top) 객체를 가져온다. 가져온 객체를 제거함

Queue

FIFO 자료구조를 구현한 클래스

Queue 객체 생성

Queue<E> queue = new Queue<E>();

Queue 클래스 주요 메소드

리턴타입메소드설명
booleanoffer(E e)주어진 객체를 추가
Epeek()가장 처음 추가된 객체(front)를 가져온다. 객체를 제거하지 않음
Epop()가장 처음 추가된 객체(front)를 가져온다. 가져온 객체를 제거

동기화된 컬렉션

대부분의 컬렉션 클래스들은 싱글 스레드 환경에서 사용할 수 있도록 설계
멀티 스레드 환경에서 무결성을 보장하지 못함
Vector와 Hashtable은 동기화된 메소드로 구성되어 있어 멀티 스레드 환경에서 안전하게 사용 가능
싱글 스레드 환경에 맞게 설계된 컬렉션 객체들을 동기화된 메소드로 래핑할 수 있도록 Collections가 메소드들을 제공

Collections의 동기화 래핑 메소드

리턴타입메소드설명
List<>synchronizedList(List list)List를 동기화된 List로 리턴
Map<K, V>synchronizedMap(Map<K, V> m)Map을 동기화된 Map으로 리턴
SetsynchronizedSet(Set s)Set을 동기화된 Set으로 리턴

Collection의 동기화 객체 생성

List<T> syncList = Collections.synchronizedList(list);
Map<K, V> syncMap = Collections.synchronizedMap(map);
Set<T> syncSet = Collections.synchronizedSet(set);

제네릭

다양한 타입의 객체들을 다루는 메소드나 클래스 타입을 미리 명시해 줌으로써 컴파일 시 타입을 체크할 수 있도록 하고, 형변환을 하는 번거로움 없이 사용하게 해주는 것으로 배열이나 이후 배울 컬렉션 사용 시 데이터 타입의 안정성을 높일 수 있다.

  • 타입 안정성
    • 의도하지 않는 타입의 객체가 저장되는 것을 막고, 저장된 객체를 의도하지 않는 타입으로 사용되는 것을 막는 것

제네릭 선언

제네릭은 클래스와 메소드에 선언 가능

제네릭 클래스 선언

[접근제한자] class [클래스이름]<Type1, Type2, ... > { }

클래스를 선언할 때 클래스 이름 옆에 <>를 이용하여 데이터 타입이나 타입 변수를 지정해주면 된다. 제네릭 타입 변수는 식별자 명명 규칙에 따라 어느 것이든 가능하지만 일반적으로 T를 많이 사용한다. 이후 클래스 내부에 변수나 메소드를 선언할 때 일반 데이터 타입과 동일하게 사용하면 되며, 타입 변수를 특정 데이터 타입으로 지정해주면 해당 타입으로 메모리에 할당하여 사용 가능하다.

public class GenericEx<T>
    T object;
 
    void setObject(T object) { this.object = object; }
    T getObject() { return object; }
}

GenericEx<String> ex = new GenericEx<String>();

만약 두 개 이상의 타입으로 제네릭 타입 변수를 사용하고 싶다면 콤마로 구분하여 다른 타입으로 타입 변수를 지정해주면 된다.

제네릭 메소드

메소드에서 사용할 타입을 제네릭을 이용하여 선언할 수 있다.

[접근제한자]<Type1, Type2, ... > [리턴타입] [메소드이름] (매개변수, ...)

제네릭 메소드를 호출할 때에는 타입 변수를 명시적으로 지정할 수도 있고 컴파일러가 매개값의 타입을 보고 추정하도록 할 수도 있다.

제네릭 제한하기

일반적인 방법으로 제네릭을 이용했을 경우 타입에 대한 제한이 없다. 하지만 제네릭 타입 변수에 extends 키워드를 사용하면 타입의 종류를 제한할 수 있다.

class Point
    int x;
    int y;
}

class Triangle<T extends Point> {
    T pos1, pos2, pos3;
}

extends 뒤에 명시된 타입의 자손들만 타입 변수에 대입할 수 있게 된다.

와일드 카드

타입 변수를 매개변수나 리턴 타입으로 사용할 때 구체적인 타입 대신 와일드 카드를 사용할 수 있다. 타입 변수를 대치할 수 있는 구체적인 타입으로 제한을 두지 않거나 extends 키워드를 이용해 해당 타입과 자손 타입들만 가능하도록 제한하거나 super 키워드를 이용해 해당 타입과 부모 타입들만 가능하도록 제한하는 방법이 있다.

와일드 카드 이용 3가지 방법

<?> : 제한 없음
<? extends 상위타입> : 상위 클래스 제한
<? super 하위타입> : 하위 클래스 제한

제네릭 상속

제네릭 클래스도 다른 클래스와 마찬가지로 부모 클래스가 될 수 있다.
부모 클래스의 제네릭 타입을 상속해서 자식 클래스에서도 제네릭 타입을 상속할 수 있다.

public class ChildProduct<T, K> extends Product<T, K> { ... }

자식 제네릭 클래스는 추가적인 타입 변수를 가질 수 있다.

public class ChildProduct<T, K, S> extends Product<T, K> { ... }

0개의 댓글

관련 채용 정보