■ 제네릭
Generics은 컬렉션(자료구조) 즉, 쉽게 말해서 객체들을 저장(수집)하는 구조적인 성격을 보강하기 위해 제공되는 것이다.
간단히 예를 들자면 컵이라는 특정 객체가 있다. 이 컵은 물만 담을 수 있는 컵, 또는 이 컵은 주스만 담을 수 있는 컵. 이렇게 상징적인 것이 바로 Generics다.
1. 제네릭의 필요성
JDK5.0에 와서 Generics가 포함되면서 이제 프로그래머가 특정 컬렉션(자료구조)에 원하는 객체 타입을 명시하여 실행하기 전에 컴파일 단계에서 지정된 객체가 아니면 절대 저장이 불가능하게 할 수 있다.
이전 버전까지는 반드시 실행하여 컬렉션(자료구조)에 있는 자원들을 하나씩 검출하여 확인할 수밖에 없었다. Object로부터 상속받은 객체는 모두 저장이 가능했던 이전의 버전들과는 달리 보다 체계적이라 할 수 있다.
실행 시 자원검출을 하게 되면 별도의 형 변환(Casting)이 필요없이 <> 사이에 선언했던 객체자료형으로 검출되어 편리하다.
2. <1글자로 된 영문대문자>
API에서는 전달되는 개체가 현 객체 내에서 자료형(Type)으로 쓰일 때 <T>로 유도를 하고 있으며 만약 전달되는 객체가 현 객체 내에서 하나의 요소(Element)로 자리를 잡을 때는 <E>로 그리고 전달되는 객체가 현 객체 내에서 Key값으로 사용될 때는 <K>로, 만약 전달되는 객체가 현 객체 내에서 Value값으로 사용될 때 <V>로 표현하고 있다.
□ 제네릭 사용하기
- Generic_class명<적용할_Generic_Type> 변수명; // 선언
- 변수명 = new Generic_class생성자명<적용할_Generic_Type>(); // 생성
package jun.java.exam00;
class GenericEx<T> {
T[] v;
public void set(T[] n) {
v = n;
}
public void print() {
for(T s : v)
System.out.println(s);
}
}
package jun.java.exam00;
public class GenericExMain {
public static void main(String[] args) {
GenericEx<String> t = new GenericEx<String>();
String[] ss = {"홍", "길", "동"};
t.set(ss);
t.print();
}
}
■ Java Collection Framework
자바에서 얘기하는 Java Collection Framework는 객체들을 한 곳에 모아 관리하고 또 그것을 편하게 사용하기 위해 제공되는 환경이다. 여기에는 다음과 같이 구조를 이루고 있다.
1. Set인터페이스 - HashSet, TreeSet
Set내에 저장되는 객체들은 특별한 기준에 맞춰서 정렬되지 않는다. 그리고 저장되는 객체들간의 중복된 요소가 발생하지 못하도록 내부적으로 관리하고 있다.
순서가 없으며, 동일한 데이터가 허용되지 않는다.
□ HashSet
기본적인 Set 인터페이스를 구현하고 있으며 정렬순서나 반복처리 시 처리순서에 대한 기준은 없다. 그리고 반복처리에 대해서는 저장된 요소(Element)의 수와는 별도로 용량에 비례하는 시간이 필요하므로 반복처리하는 성능이 중요한 응용프로그램에서는 초기 용량을 너무 높게 설정하지 않는 것이 중요하다.
- 주요 메소드
package jun.java.exam01;
import java.util.HashSet;
import java.util.Iterator;
class AData { // 무한데이터에 들어가는 데이터는 무조건 클래스임
int x;
int y;
public AData(int x, int y) {
this.x = x;
this.y = y;
}
public void disp() {
System.out.println("x = " + x + ", y = " + y);
}
}
public class HashSetEx {
public static void main(String[] ar) {
AData ap = new AData(10,20);
AData bp = new AData(20,30);
AData cp = new AData(30,40);
HashSet<AData> hs = new HashSet<AData>(); // <AData> -> 제네릭을 걸어
hs.add(ap);
hs.add(bp); // AData 아닌 걸 넣으려고 하면 X
hs.add(cp);
System.out.println("해시코드 : " + hs.hashCode());
System.out.println("총 데이터 크기 : " + hs.size());
Iterator<AData> it = hs.iterator();
while(it.hasNext())
it.next().disp(); // 제네릭을 걸어서 형변환을 안 해도 된다.
}
}
// 결과값이 순서대로 나오지 않는다.
// 랜덤이다
<결과>
해시코드 : 1619887429
총 데이터 크기 : 3
x = 30, y = 40
x = 10, y = 20
x = 20, y = 30
2. List 인터페이스 - Stack, Vector, ArrayList
List 구조는 Sequence라고도 하며 시작과 끝이 선정되어 저장되는 요소들을 일괄적인 정렬상태를 유지하면서 요소들의 저장이 이루어진다. 이런점 때문에 List 구조하면 배열을 연상하게 되는데 무리는 아니다. 어떻게 보면 배열과 컬렉션의 List 구조는 같다고 볼 수 있으며 다르다면 배열은 크기가 고정되어 있는 것이고 컬렉션의 List 구조는 가변적 길이를 가진다는 는 것이다.
□ Stack
Stack은 객체를 후입선출, last in first out (LIFO)이며 객체의 저장시의 push() 메소드와 검출 시 사용하는 pop()과 Stack의 가장 위쪽 객체를 의미하는 peek() 메소드 그리고 Stack이 비어있는지 판별해주는 empty()와 객체를 검색해주는 search() 메소드들로 Vector라는 클래스를 확장하였다.
package jun.java.exam02;
import static java.lang.System.out;
import java.util.Stack;
public class StackEx {
public static void main(String[] args) {
String[] groupA = {"우즈베키스탄", "쿠웨이트", "사우디", "대한민국"};
Stack<String> stack = new Stack<String>();
for(String n : groupA)
stack.push(n);
while(!stack.isEmpty())
out.println(stack.pop());
}
// 들어갔던 순서의 역순으로 나온다.
}
<결과>
대한민국
사우디
쿠웨이트
우즈베키스탄
3. Queue 인터페이스 - LinkedList
JDK5.0에 오면서 새롭게 추가된 인터페이스이며 Queue의 구조는 도로의 일정구간인 일방통행과 같다. 요소(Element)가 들어가는 입구와 요소(Element)가 나오는 출구가 따로 준비 되어있어 가장 먼저 들어간 요소(Element)가 가장 먼저 나오는 선입선출, first in first out (FIFO) 방식이다.
□ LinkedList
LinkedList는 add() 메소드와 poll() 메소드 등에 의해 선입선출법을 제공하는 Queue 인터페이스를 구현하며 Thread 동기화는 제공되지 않는다.
package jun.java.exam03;
import static java.lang.System.out;
import java.util.LinkedList;
public class QueueEx {
public static void main(String[] args) {
String[] item = {"소나타", "렉스톤", "제규어"};
LinkedList<String> q = new LinkedList<String>();
for(String n : item)
q.offer(n); // 요소 추가
out.println("q의 크기 : " + q.size());
String data = "";
while((data = q.poll()) != null) {
out.println(data + "삭제");
out.println("q의 크기 : " + q.size());
}
// <String> -> 제네릭
// .offer -> 추가
}
}
<결과>
q의 크기 : 3
소나타삭제
q의 크기 : 2
렉스톤삭제
q의 크기 : 1
제규어삭제
q의 크기 : 0
4. Map 인터페이스 - HashMap, HashTble
Key와 Value를 mapping하는 객체이다. 여기에 사용되는 Key는 절대 중복될 수 없으며 각 Key는 1개의 Value만 mapping할 수 있다. 정렬의 기준이 없으며 이는 마치 각 Value에 열쇠고리를 달아서 큰 주머니에 넣어두고 오로지 Key로 각 Value를 참조할 수 있도록 해둔 구조라 할 수 있다.
사용자가 원하는 Value의 Key를 알고 있다면 Key를 당겨(get) 해당 Key와 매핑되어 있는 Value를 얻을 수 있는 구조이다. 즉 검색을 Key로 해야 하므로 Key를 모르면 원하는 Value를 얻을 수 없다.
□ HashMap
Key와 Value를 하나의 쌍으로 저장되는 구조이며 저장되는 Value와 Key가 null을 허용한다. 하지만 중복은 허용하지 않으므로 null을 가지는 Key가 2개일 수는 없다. 그리고 동기화가 포함되지 않았으므로 나중에 배우는 Multi-Thread 환경에서의 구현이 아니라면 Hashtable에 비해서 처리속도가 빠른 장점을 가지고 있다.
- 주요 메소드 ( pull(), remove() 반환형 V가 아니라 void이다)
package jun.java.exam04;
import static java.lang.System.out;
import java.util.HashMap;
import java.util.Set;
public class MapEx {
public static void main(String[] args) {
String[] msg =
{"Berlin", "Dortmund", "Frankfurt", "Gelsenkirchen", "Humburg"};
HashMap<Integer, String> map =
new HashMap<Integer, String>(); // HashMap 생성
for(int i=0; i<msg.length; i++)
map.put(i, msg[i]); // 맵에 저장
Set<Integer> keys = map.keySet();
for(Integer n : keys)
out.println(map.get(n)); // 맵에서 읽어오기
}
}
<결과>
Berlin
Dortmund
Frankfurt
Gelsenkirchen
Humburg
map.put(i, msg[i]) 원래 에러다.
<Integer>는 Wrapper클래스, i는 Integer
예전에는 new Integer(i) 로 써야 한다
객체가 와야 하는데 자료형이 오면 알아서 객체로 포장해준다 -> Autoboxing
이제는 예전방식으로 쓰면 오류가 난다.
i자리를 예전 방식으로 쓸거면 Interger.valueOf(i)로 써야한다 .
값이와야 하는데 클래스가 오면 자동으로 값으로 바꿔준다. -> UnBoxing
'IT&코딩 > Java' 카테고리의 다른 글
Java - 17일차 (Java IO - File) (0) | 2022.11.03 |
---|---|
Java - 16일차 (Event) - X (0) | 2022.11.03 |
Java - 14일차 (패키지, 예외처리, 단언) (0) | 2022.11.01 |
Java - 13일차 (알아두면 유용한 클래스) (2) | 2022.10.29 |
Java - 12일차 (이너클래스와 열거형) (0) | 2022.10.28 |