// collection 주요 특징
1. generic 기법 <E>, <V>, <K> - 타입 매개변수 (generic type)
Vector<Integer> // Integer 객체만
2. collection 요소 = only 객체
int, char, double, boolean 등 기본 type 불가
Vector<int> v = new Vector<int>(); // error
Vector<Integer> v = new Vector<Integer>(); // O
// 단. 삽입은 기본 타입으로 가능 (자동 boxing)
v.add(3); // int 타입 -> Integer 자동 boxing// colletction class (개발자 바로 사용 가능)
Collection<E> // 상위 클래스 (아래 모두 Collection<E> 상속 받음)
Vector<E> // 배열
ArrayList<E>
LikedList<E> // 연결 리스트
Stack<E> // 스택
HashSet<E> // 집합 (set)// 제네릭 타입 매개변수
// <E> : element - 컬렉션 요소
// <T> : type
// <V> : value
// <K> : key
class Stack<E> {
...
void push(E element) { ... }
E pop() { ... }
}
// E -> Integer : Integer 객체만 다루는 stack (구체화)
class Stack<Integer> {
...
void push(Integer element) { ... }
Integer pop() { ... }
}Vector - 자동 크기 x 2
synchronized (동기화) & thread-safe → multi thread에서 유리
// Vector<E> - 배열 가변 크기 (자동 크기 조절, 자리 이동)
// full -> 자동으로 크기 x 2
Vector<Integer> v = new Vector<Integer>();
Vector v = new Vector(); // type 지정 안 할 시, 경고
// 활용법 (null 도 삽입 가능)
Vector<Integer> v = new Vector<Integer>(7); // 크기 7 지정
v.add(Integer.valueOf(5)); // v.add(5) 와 동일
v.add(5); // 맨 뒤에 자동 삽입 (자동 boxing)
v.add(4);
v.add(-1); // 5 4 -1 순
int n = v.size(); // size : 사용 중인 크기 = 3
int c = v.capacity(); // capacity : 전체 배열 크기 = 7
v.add(2, 100); // 5 4 100 -1 (index 2에 100 삽입)
v.add(3, null); // 5 4 100 null -1 (null 삽입 가능)
v.add(5, 100); // error - v.size() 보다 큰 곳에 삽입 불가
Integer obj = v.get(1); // Integer 타입의 객체 (4) 가져옴
int i = obj.intValue(); // i = 4
int j = v.get(1); // j = 4, (자동 unboxing)
v.remove(1); // index 1의 요소 삭제 - 5 100 null -1 (index 삭제)
Integer m = Integer.valueOf(100);
v.remove(m); // 레퍼런스 이용 삭제 - 5 null -1 (레퍼런스 삭제)
int last = v.lastElement(); // 마지막 요소
v.removeAllElements(); // 모두 삭제 & 크기 0
v.clear(); // 모두 삭제
import java.util.*;
public class VectorEx {
public static void printVector(Vector<Integer> v) {
for (int i = 0; i < v.size(); i++)
System.out.println(v.get(i)); // 자동 unboxing
}
public static void main(String[] args) {
Vector<Integer> v = new Vector<Integer>(); // Java 7 이전
Vector<Integer> v = new Vector<>(); // Java 7 이후 (추론)
var v = new Vector<Integer>(); // Java 10 이후 (var 사용)
v.add(5);
v.add(3);
v.add(1, 100);
printVector(v); // 5 100 3 출력
}
}
ArrayList - vector와 달리 thread 자동 동기화 X (크기 50% 증가)
asychronous (비동기) & not thread-safe → single thread에 유리
safety checking 없어서 vector보다 빠름 / 크기 50%씩 증가
import java.util.*;
ArrayList<String> al = new ArratList<String>();
al.add("Hello");
al.add("Hi");
al.add("Java"); // Hello Hi Java
int n = al.size(); // n = 3
int c = al.capacity(); // error - ArrayList는 capacity 없음
al.add(2, "Sahni"); // Hello Hi Sahni Java
String str = al.get(1); // str = "Hi"
al.remove(1); // Hello Sahni Java
al.remove("Sahni"); // Hello Java
al.clear();
Iterator - 순차 검색을 위한 interface - hasNext(), next(), remove()
// Iterator<E> : <E>에는 컬렉션과 동일한 타입 매개변수
// 주요 method
boolean hasNext() // 다음 요소 존재 - true
E next() // 다음 요소 return
void remove() // 마지막 return 요소 제거
Vector<Integer> v = new Vector<Integer>();
Iterator<Integer> it = v.iterator(); // iterator interface 선언
int sum = 0;
// v.size() 로 순회
for (int i = 0; i < v.size(); i++)
sum += v.get(i);
// iterator로 순회
while(it.hasNext()) {
int n = it.next();
sum += n;
}
it = v.iterator(); // 처음으로 지정해주려면 선언 다시 해야됨
HashMap<K, V> - key (data type), value (type 매개변수) put()
장점 : 요소 삽입, 삭제, 검색 매우 빠름 / 단점 : key로만 접근 가능
// 주요 method
void clear() // 모든 요소 삭제
boolean containsKey(Object key) // key값 갖고 있으면 true
boolean containsValue(Object value) // value 갖고 있으면 true
V get(Object key) // key에 대한 value 리턴
Set<K> keySet() // 모든 key 담은 Set<K> 컬렉션 return
V put(K key, V value) // 저장 (key, value)
V remove(K key) // key, value 쌍 모두 삭제
int size() // HashMap size
import java.util.*;
public class HashMapEx {
public static void main(String[] args) {
HashMap<String, String> dic = new HashMap<String, String>();
dic.put("baby", "아기"); // 삽입
dic.put("love", "사랑");
dic.put("apple", "사과");
Set<String> keys = dic.keySet(); // key 집합
Iterator<String> it = keys.iterator(); // iterator 선언
while(it.hasNext()) { // dic 모두 출력
String word = it.next();
System.out.println("(" + word + ", " + dic.get(word) + ")");
}
Scanner scanner = new Scanner(System.in);
while(true) {
System.out.print("찾고 싶은 단어 : ");
String eng = scanner.next();
if (eng.equals("exit")) {
System.out.println("시스템 종료");
break;
}
String kor = dic.get(eng); // 검색
if (kor == null)
System.out.println("사전에 없는 단어");
else
System.out.println(kor);
}
scanner.close();
}
}
LinkedList - 양방향 연결 관리 - head, tail
head, tail 레퍼런스 통해 맨 뒤, 맨 앞 접근 가능 (stack, queue로 활용)
Collections 클래스 - static : 생성자 필요 없음
정렬 (sort), 반대로 (reverse), 최대 최소(max, min), 이진 탐색 (binarySearch())
import java.util.*;
public class CollectionEx {
static void printList(LinkedList<String> l) {
Iterator<String> it = l.iterator();
while (it.hasNext()) {
String e = iterator.next();
String separator;
if (iterator.hasNext())
separator = "->";
else
separator = "\n";
System.out,print(e + separator);
}
}
public static void main(String[] args) {
LinkedList<String> l = new LinkedList<String>();
l.add("트랜스포머");
l.add("스타워즈");
l.add("매트릭스");
l.add(0, "터미네이터");
l.add(2, "아바타"); // 터 트 아 스 매
Collections.sort(l); // 가나다 순 정렬
printList(l); // 매->스->아->터->트
Collections.reverse(l); // 역순
printList(l); // 트->터->아->스->매
int index = Collections.binarySearch(l, "아바타") + 1;
System.out.println("아바타는" + index + "번째 요소"); // 3
}
}
// 제네릭 클래스 작성
public class MyClass<T> {
T val; // 변수 val의 타입은 T
void set(T a) {
val = a;
}
T get() {
return val;
}
}
// 제네릭 클래스에 대한 레퍼런스 선언
MyString<String> s;
List<Integer> li;
Vector<String> vs;
// 구체화
MyClass<String> s = new MyClass<String>(); // String으로 지정
s.set("hello");
System.out.println(s.get()); // hello 출력
MyClass<Integer> i = new MyClass<Integer>(); // Integer로 지정
i.set(10); // 자동 boxing
System.out.println(i.get()); // 10 출력 제네릭 타입 가진 객체 생성 불가 - 아래 error 코드// error code
public class MyVector<E> {
E create() {
E a = new E(); // error - 타입 E를 모르기 때문
return a;
}
}// Generic Stack 생성
class GStack<T> {
int tos;
Object[] stck; // 배열
public GStack() { // 생성자
tos = 0;
stck = new Object[10]; // 10칸 배열 생성
stck = new T[10]; // error - 제네릭 타입 불가
}
public void push(T item) {
if (tos == 10) // full
return;
stck[tos] = item;
tos++;
}
public T pop() {
if (tos == 0) // empty
return null;
tos--;
return (T)stck[tos]; // 타입 매개변수 type으로 캐스팅
// stck = Object[10]; 으로 Object 타입으로 선언했으므로 강제 캐스팅 필요
}
}
public class MyStack {
public static void main(String[] args) {
GStack<String> stringStack = new GStack<String>(); // String Stack
stringStack.push("seoul");
stringStack.push("busan");
stringStack.push("LA");
for (int i = 0; i < 3; i++)
System.out.println(stringStack.pop()); // La busan seoul
GStack<Integer> intStack = new GStack<Integer>(); // Integer Stack
intStack.push(1);
intStack.push(3);
intStack.push(5);
for (int i = 0; i < 3; i++)
System.out.println(intStack.pop()); // 5 3 1
}
}
// 제네릭과 배열 - 제네릭 클래스, 인터페이스 타입 배열 불가
GStack<Integer>[] intStack = new GStack<Integer>[10]; // error
T[] a = new T[10]; // error
public void myArray(T[] a) { ... } // 레퍼런스로는 가능
// 제네릭 method
class GenericMethodEx {
static <T> void toStack(T[] a, GStack<T> gs) { // T가 타입 매개변수인 제네릭 메소드
for (int i = 0; i < a.length; i++)
gs.push(a[i]);
}
}// 제네릭 장점
1. compile시 type 구체화 -> 안전한 프로그래밍 가능
2. runtime 타입 충돌 방지
3. 타입 캐스팅 불필요
4. ClassException 방지