처음부터 시작하는 프로그래밍
제네릭 본문
제네릭이란?
제네릭 프로그래밍(generic programming)이란
다양한 종류의 데이터를 처리할 수 있는 클래스와 메소드를 작성하는 기법
컬렉션이란
자료구조들을 제네릭 형식으로 제공해주는 자바 라이브러리
제네릭을 사용하게 되면 각각의 자료형으로 선언해줄 필요가 없기 때문에 편리하게 이용이 가능하다.
C++ 표준 템블릿 라이브러리, STL
STL(Standard Template Library)
표준 템플릿 라이브러리
- C++ 표준 라이브러리 중 하나
많은 제네릭 클래스와 제네릭 함수 포함
- 개발자는 이들을 이용하여 쉽게 응용 프로그램 작성
STL의 구성
컨테이너(container) - 템플릿 클래스
- 데이터를 담아두는 자료 구조를 표현한 클래스
- list, queue, stack, map, set, vector
iterator - 컨테이너 원소에 대한 포인터
- 컨테이너의 원소들을 순회하면서 접근하기 위해 만들어진 컨테이너 원소에 대한 포인터
알고리즘 - 템플릿 함수
- 컨테이너 원소에 대한 복사, 검색, 삭제, 정렬 등의 기능을 구현한 템플릿 함수
컨- 테이너의 멤버 함수 아님
// 제네릭 예제 1
class Box <T> {
private T data;
public void set(T data){
this.data = data;
}
public T get(){
return data;
}
}
public class objBox {
public static void main(String[] args) {
Box b = new Box();
b.set("Hello World!");
String s = (String) b.get();
b.set(new Integer(10));
Integer i = (Integer) b.get();
System.out.println(i);
}
}
위 코드 블럭에 main 함수는 box클래스의 set, get 함수에 대해 String 값과 Integer 값을 주고 있다.
이를 처리하기 위해서는 함수에 대해 각각의 파라메터를 따로 오버로딩 하는 방법또한 있지만, 이를 제네릭을 이용해서 클래스를 작성하게 되면 오버로딩을 하지 않고도 각각의 자료형에 대해 제네릭이 그 값을 읽고 처리해준다.
// 제네릭 예제 2
class SimplePair <T> {
T data1;
T data2;
public SimplePair (T data1, T data2){
this.data1 = data1;
this.data2 = data2;
}
public T getFirst() {
return data1;
}
public T getSecond() {
return data2;
}
}
public class SimplePairTest {
public static void main(String[] args) {
SimplePair<String> pair = new SimplePair<String> ("apple", "tomato");
System.out.println(pair.getFirst());
System.out.println(pair.getSecond());
SimplePair<Integer> pairInt = new SimplePair<Integer>(10, 20);
System.out.println(pairInt.getFirst());
System.out.println(pairInt.getSecond());
}
}
// 제네릭 예제 3
class OrderedPair <K, V> {
K key;
V value;
public OrderedPair (K key, V value){
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
}
public class OrderedPairTest {
public static void main(String[] args) {
OrderedPair <String, Integer> p1 = new OrderedPair <String, Integer> ("mykey", 12345678);
OrderedPair <String, String> p2 = new OrderedPair <String, String> ("java", "a programming langauge");
System.out.println(p1.getKey() + " " + p1.getValue());
System.out.println(p2.getKey() + " " + p2.getValue());
}
}
대표주자 ArrayList
ArrayList <String>: String 객체를 저장하는 ArrayList
String[] 배열 보다 매우 편리함
자동적으로 배열의 크기가 변경되기 떄문!
stack
모든 원소의 삽입과 삭제가 한 쪽 끝에서 일어나는 순서 리스트
후입 선출(Last In First Out : LIFO)
- 제일 최근에 들어온 원소가 제일 먼저 삭제됨
스택의 동작
- push: 원소를 삽입하는 동작
- pop: 원소를 삭제하는 동작
- tos: stack의 최상위 원소를 가리키는 pointer 로, 원소의 개수에 따라 유동적으로 변화함. (삽입 1증가, 삭제 1감소)
- bottom: stack의 최하위 원소를 가리키는 pointer 로, 항상 0임
Stack의 크기가 n일 경우
- tos 포인터는 n을 초과할 수 없으며, 0미만일 수 없다.
tos 포인터가 bottom 포인터와 같거나, 0인 경우 stack이 비워있음을 알 수 있으며
tos 포인터가 n일 경우, stack이 꽉 차 있음을 알 수 있다.
stack의 기본 동작 원리
// 제네릭을 이용한 스택의 동작
class Gstack <T> {
int tos; // top of stack
Object[] stck;
Gstack(){
tos = 0;
stck = new Object[10];
}
public void push(T item){
if(tos == 10) return;
stck[tos++] = item;
}
public T pop(){
if(tos == 0) return null;
return (T)stck[--tos];
}
}
public class MyStack {
public static void main(String[] args) {
Gstack strStck = new Gstack<String>();
strStck.push("Seoul");
strStck.push("Busan");
strStck.push("LA");
System.out.println(strStck.pop());
System.out.println(strStck.pop());
Gstack<Integer> intStk = new Gstack<Integer>();
intStk.push(1);
intStk.push(3);
intStk.push(5);
System.out.println(intStk.pop());
System.out.println(intStk.pop());
System.out.println(intStk.pop());
}
}
제네릭 메소드
일반 클래스의 메소드에서도 타입 매개 변수를 사용하여 제네릭 메소드를 정의할 수 있다.
이 경우에는 타입 매개 변수의 범위가 메소드 내부로 제한된다.
// 제네릭 메소드 예제1
class MyArrayAlg{
public static <T> T getLast(T[] a){
return a[a.length - 1];
}
}
public class MyArrayAlgTest {
public static void main(String[] args) {
String[] language = {"C++", "C#", "JAVA"};
String last = MyArrayAlg.getLast(language);
System.out.println(last);
Integer[] langCode = {1,2,3};
Integer intlast = MyArrayAlg.getLast(langCode);
System.out.println(intlast);
}
}
// 제네릭 메소드 예제2
class MyArrayAlg{
public static <T> void swap(T[] a, int i, int j) {
T temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
public class MyArrayAlgTest {
public static void main(String[] args) {
String[] lang = { "C++", "C#", "JAVA" };
MyArrayAlg.swap(lang, 1, 2);
for(String val : lang)
System.out.println(val);
}
}
// 제네릭 메소드 예제3
public class GenericMethodTest {
public static void main(String[] args) {
Integer[] iArray = {10,20,30,40,50};
Double[] dArray = {1.1,1.2,1.3,1.4,1.5};
Character[] cArray = { 'K', 'O', 'R', 'E', 'A'};
printArray(iArray);
printArray(dArray);
printArray(cArray);
}
static <T> void printArray(T[] array) {
for(T element : array)
System.out.print(element + " ");
System.out.println();
}
}
'Java' 카테고리의 다른 글
multithread program (0) | 2021.11.30 |
---|---|
컬렉션 (0) | 2021.11.30 |
파일 입출력 (0) | 2021.11.18 |
Exception Class (0) | 2021.11.16 |
패키지 (0) | 2021.11.09 |