Vector, ArrayList, Set, LinkedList와 같이 순서대로 요소가 저장된 컬렉션에서 순차 검색을 하려는 경우 java.util 패키지의 Iterator<E> 인터페이스를 이용할 수 있다. 이 때 타입 매개변수로 컬렉션의 매개변수와 동일한 타입으로 지정해야 한다. 다음은 벡터의 이터레이터 객체를 생성하는 예시이다.
Vector<Integer> v = new Vector<Integer>();
Iterator<Integer> it = v.iterator();
Iterator<E> 인터페이스의 메소드는 다음과 같다.

이 때, 메소드 next()의 리턴 타입은 제네릭으로 되어있다.
벡터 v의 iterator() 메소드를 호출하여 벡터의 각 요소를 순차적으로 검색할 수 있도록 하는 Iterator 객체 it를 생성한다.
다음과 같이 객체 it를 통해 벡터의 각 요소를 순차 검색 할 수 있다.
while(it.hasNext()){ //벡터의 모든 값에 대해 반복
int n = it.next(); //it가 가리키는 요소 리턴
System.out.println(n);
...
}
해시맵 컬렉션의 경로는 java.util.HashMap이며 key와 value의 쌍으로 구성된다. 해시맵은 다음과 같이 생성한다.
HashMap<String, String> h = new HashMap<String, String>();
해시맵은 키와 값을 저장하는 각각의 자료 구조를 가진다. 해시맵 객체의 구성은 다음과 같다.

다음은 해시맵의 주요 메소드이다.

put() 메소드에 키와 값을 전달해 요소를 삽입한다.
h.put("사과", "빨강색");
h.put("바나나", "노랑색");
h.put("블루베리", "파랑색");
put() 메소드는 키와 값을 받아 키를 이용해 해시 함수를 실행하고 해시 함수가 리턴한 위치에 키와 값을 저장한다.
get() 메소드에 키를 전달하면 값을 리턴한다. 키를 이용해 해시 함수를 실행하여 값이 저장된 위치를 알아내고 값을 반환한다.
String clr1 = h.get("사과");
String clr2 = h.get("바나나");
String clr3 = h.get("사과");
String clr4 = h.get("복숭아");
System.out.println(clr1);
System.out.println(clr2);
System.out.println(clr3);
System.out.println(clr4);
빨강색
노랑색
빨강색
null
해시맵에 저장되어있지 않은 키값으로 get() 호출 시 null을 리턴한다.
remove() 메소드를 이용하면 키를 통해 요소를 삭제할 수 있다.
h.remove("블루베리");
size() 메소드로 해시맵 요소의 개수를 알아낼 수 있다.
int n = h.size();
해시맵 컬렉션을 생성하고 요소를 삽입, 삭제하는 과정은 다음과 같다.

keySet() 메소드는 모든 키를 Set 컬렉션으로 만들어 리턴한다. 키 Set의 모든 값을 get()에 대입하면 해시맵 전체 요소를 검색할 수 있다.
Set<String> keys = h.keySet();
Iterator<String> it = keys.iterator();
while(it.hasNext()){
String key = it.next();
String value = h.get(key);
System.out.println("<" + key + " : " + value + ">");
}
<사과 : 빨강색>
<바나나 : 노랑색>
해시맵은 Vector나 ArrayList와 같이 List 인터페이스를 상속 받은 컬렉션과 차이가 있다.
get() 메소드 호출 시 해시 함수가 키가 저장된 위치를 즉각 찾아내므로 검색 시간이 빠르다.
해시맵은 해시함수를 사용하며 다른 요소들의 위치 이동이 필요하지 않으므로 요소의 삽입, 삭제 시간이 빠르다.
해시맵에서 요소 삽입 순서와 위치를 결정할 수 없으므로 인덱스를 사용할 수 없다.
LinkedList<E>는 경로명이 java.util.LinkedList이며 List<E> 인터페이스를 구현한 클래스이다. 요소를 양방향으로 연결하며 맨 앞과 맨 뒤를 가리키는 head, tail 레퍼런스를 가진다. 앞, 뒤, 중간에 요소의 삽입이 쉽게 이루어지며 인덱스를 사용할 수 있다.
add()를 통해 요소를 삽입하며 get() 메소드에 인덱스를 전달하여 요소에 접근한다.
java.util 패키지의 Collection 클래스는 Collection 클래스를 다룰 때 공통으로 사용되는 메소드이다.
제네릭 클래스를 만드려면 타입 매개변수를 추가하여 클래스를 작성하면 된다. 타입 매개변수로는 주로 E, T, V, K와 같은 대문자 알파벳을 사용한다.
다음과 같이 제네릭 클래스를 작성한다.
class NewClass<T>{
T val; //타입이 T인 변수 val
void set(T t){
val = t;
}
T get(){
return val;
}
}
레퍼런스 변수 선언 시 타입 매개변수에 타입을 기재한다.
NewClass<String> s;
NewClass<Integer> I;
제네릭 클래스에 타입을 대입해 구체적인 객체를 생성하는 과정을 구체화라고 한다. 이 과정은 자바 컴파일러에 의해 이루어지며 다음과 같dl 생성할 수 있다.
NewClass<String> s = new NewClass<String>();
s.set("String");
System.out.println(s.get());
NewClass<Integer> i = new NewClass<Integer>();
i.set(100);
System.out.println(i.get());
String
100
❗제네릭 클래스의 구체화에 기본 타입은 사용할 수 없다.
제네릭 클래스 내에서 제네릭 타입을 가진 객체를 생성할 수 없다. 제네릭 매개면수로 배열의 생성 또한 불가하다. 따라서 Object 배열을 생성하여 원하는 타입의 객체를 삽입해야 한다.
제네릭 클래스 또는 인터페이스 타입의 배열을 선언할 수 없다. 다만 제네릭 타입의 배열 선언은 가능하다. 이 때 선언만 가능하고 생성할 수 없다.
GStack<Integer>[] gs = new GStack<Integer>[10]; //오류
public void GArray(T[] a) { ... } //허용
클래스의 일부 메소드만 제네릭으로 구현할 수 있다. 다음과 같이 메소드의 리턴 타입 앞에 타입 매개변수를 선언한다.
class NewClass{
static <T> void func(T[] a, GStack<T> gs){
...
}
}
제네릭 메소드를 호출할 때에는 타입을 명시하지 않아도 된다.
❗제네릭 클래스, 인터페이스는 명시 필요❗