컬렉션 프레임워크란?
- 다수의 데이터를 쉽고 효과적으로 처리할 수 있는 표준화된 방법을 제공하는 클래스 집합을 컬렉션 프레임워크라 함
- 컬렉션 프레임워크에는 List, Set, Map 인터페이스가 구현되어 있음
- 컬렉션 프레임워크에 속하는 인터페이스들을 구현한 것을 컬렉션 클래스라고 함
List
- List 컬렉션 클래스는 요소의 저장 순서가 유지되며, 같은 요소의 중복 저장을 허용한다는 특징이 있음
- List 컬렉션 클래스에는 대표적으로 ArrayList, LinkedList, Stack이 속해있음
ArrayList
- 배열을 사용해 요소를 저장하는 List 컬렉션 클래스
- 인덱스를 이용해 배열 요소에 빠르게 접근할 수 있지만, 크기 변경이 필요할때 새로운 배열을 생성해야해 속도가 저하됨
ArrayList<Integer> arrList = new ArrayList<Integer>();
arrList.add(40);
arrList.add(20);
arrList.add(30);
arrList.add(10);
for (int i = 0; i < arrList.size(); i++) {
System.out.print(arrList.get(i) + " ");
}
arrList.remove(1);
for (int e : arrList) {
System.out.print(e + " ");
}
Collections.sort(arrList);
Iterator<Integer> iter = arrList.iterator();
while (iter.hasNext()) {
System.out.print(iter.next() + " ");
}
arrList.set(0, 20);
for (int e : arrList) {
System.out.print(e + " ");
}
System.out.println("리스트의 크기 : " + arrList.size());

LinkedList
- ArrayList와 거의 동일한 기능을 가지나, 배열이 아닌 연결 리스트를 사용하는 방식
- 동적인 크기변경에 유리하나, 요소의 참조에 있어서는 불리함
Stack
- List 컬렉션의 Vector 클래스 일부를 상속받아 스택 메모리 구조를 제공하는 클래스
Stack<Integer> st = new Stack<Integer>();
st.push(4);
st.push(2);
st.push(3);
st.push(1);
System.out.println(st.peek());
System.out.println(st);
System.out.println(st.pop());
System.out.println(st);
System.out.println(st.search(4));
System.out.println(st.search(3));
Queue
- Queue 인터페이스는 별도의 인터페이스로 제공되며 이를 상속받는 하위 인터페이스로는 Deque, BlockingDeque, BlockingQueue, TransferQueue가 있음
- 큐 메모리 구조를 표현하기 위해 컬렉션 인터페이스의 일부만을 상속받아 사용함
- 빠른 큐를 구현하기 위해서는 Deque 인터페이스를 구현한 ArrayDeque 클래스를 사용하면 됨
Deque<Integer> qu = new ArrayDeque<Integer>();
qu.add(4);
qu.add(2);
qu.add(3);
qu.add(1);
System.out.println(qu.peek());
System.out.println(qu);
System.out.println(qu.poll());
System.out.println(qu);
qu.remove("하나");
System.out.println(qu);
Set
- Set 컬렉션 클래스는 요소의 저장 순서를 유지하지 않고, 같은 요소의 중복저장을 허용하지 않는 특징을 가짐
- 대표적인 Set 컬렉션 클래스로는 HashSet, TreeSet이 있음
HashSet
- 해시 자료구조를 사용해 구현된 Set 클래스
- 해시 알고리즘 사용으로 검색 속도가 매우 빠르다는 장점이 있음
- 요소의 저장순서를 기록해야 하는 경우 LinkedHashSet 클래스를 사용해야 함
HashSet<String> hs01 = new HashSet<String>();
HashSet<String> hs02 = new HashSet<String>();
hs01.add("홍길동");
hs01.add("이순신");
System.out.println(hs01.add("임꺽정"));
System.out.println(hs01.add("임꺽정"));
for (String e : hs01) {
System.out.print(e + " ");
}
hs02.add("임꺽정");
hs02.add("홍길동");
hs02.add("이순신");
Iterator<String> iter02 = hs02.iterator();
while (iter02.hasNext()) {
System.out.print(iter02.next() + " ");
}
System.out.println(hs02.size());
TreeSet
- 데이터를 이진 트리 형태로 저장하는 Set 컬렉션 클래스
- 인스턴스에 저장되는 요소들은 모두 정렬된 상태로 저장됨
TreeSet<Integer> ts = new TreeSet<Integer>();
ts.add(30);
ts.add(40);
ts.add(20);
ts.add(10);
for (int e : ts) {
System.out.print(e + " ");
}
ts.remove(40);
Iterator<Integer> iter = ts.iterator();
while (iter.hasNext()) {
System.out.print(iter.next() + " ");
}
System.out.println(ts.size());
System.out.println(ts.subSet(10, 20));
System.out.println(ts.subSet(10, true, 20, true));
Map
- map 컬렉션은 key-value 방식을 사용해 컬렉션의 데이터를 저장해둠
- 키의 중복을 허용하지 않으며, 요소의 저장 순서를 유지하지 않는다는 특징을 가짐
- Map 컬렉션 클래스에 속하는 클래스로는 HashMap, TreeMap이 있음
HashMap
HashMap<String, Integer> hm = new HashMap<String, Integer>();
hm.put("삼십", 30);
hm.put("십", 10);
hm.put("사십", 40);
hm.put("이십", 20);
System.out.println(hm.keySet());
for (String key : hm.keySet()) {
System.out.println(String.format("key : %s, value : %s", key, hm.get(key)));
}
hm.remove("사십");
Iterator<String> keys = hm.keySet().iterator();
while (keys.hasNext()) {
String key = keys.next();
System.out.println(String.format("key : %s, value : %s", key, hm.get(key)));
}
hm.replace("이십", 200);
for (String key : hm.keySet()) {
System.out.println(String.format("key : %s, value : %s", key, hm.get(key)));
}
System.out.println("맵의 크기 : " + hm.size());
Iterator
- 컬렉션에 저장된 요소들을 읽어오기 위해서 Iterator 메서드를 사용할 수 있음
LinkedList<Integer> lnkList = new LinkedList<Integer>();
lnkList.add(4);
lnkList.add(2);
lnkList.add(3);
lnkList.add(1);
Iterator<Integer> iter = lnkList.iterator();
while (iter.hasNext()) {
System.out.print(iter.next() + " ");
}
- List 사용시에는 역방향 이동이 가능한 listIterator 메서드를 지원함
LinkedList<Integer> lnkList = new LinkedList<Integer>();
lnkList.add(4);
lnkList.add(2);
lnkList.add(3);
lnkList.add(1);
ListIterator<Integer> iter = lnkList.listIterator();
while (iter.hasNext()) {
System.out.print(iter.next() + " ");
}
while (iter.hasPrevious()) {
System.out.print(iter.previous() + " ");
}
- 실제 코드 작성시에는 Enhannced for문 사용을 권장함
Comparable
- 자바에서는 Boolean을 제외한 래퍼 클래스나 클래스의 인스턴스들을 정렬하기 위해 Comparable 인터페이스를 사용할 수 있음
- 인터페이스 내부의 compareTo 메서드를 구현해 객체를 정렬할 수 있음
class Car implements Comparable<Car> {
private String modelName;
private int modelYear;
private String color;
Car(String mn, int my, String c) {
this.modelName = mn;
this.modelYear = my;
this.color = c;
}
public String getModel() {
return this.modelYear + ", " + this.modelName + " " + this.color;
}
public int compareTo(Car obj) {
if (this.modelYear == obj.modelYear) {
return 0;
} else if(this.modelYear < obj.modelYear) {
return -1;
} else {
return 1;
}
}
}
public class Comparable01 {
public static void main(String[] args) {
Car car01 = new Car("아반떼", 2016, "노란색");
Car car02 = new Car("소나타", 2010, "흰색");
System.out.println(car01.compareTo(car02));
}
}
- Comparable 인터페이스를 구현한 클래스는 기본적으로 구현의 오름차순으로 정렬됨
- 만약 다른 기준으로 정렬이 필요하다면 Comparator 인터페이스를 사용
- Comparator 인터페이스를 구현한 클래스에서는 compart() 메서드를 오버라이딩 해 사용하게 됨
import java.util.*;
class DescendingOrder implements Comparator<Integer> {
public int compare(Integer o1, Integer o2) {
if(o1 instanceof Comparable && o2 instanceof Comparable) {
Integer c1 = (Integer)o1;
Integer c2 = (Integer)o2;
return c2.compareTo(c1);
}
return -1;
}
}
public class Comparable02 {
public static void main(String[] args) {
TreeSet<Integer> ts = new TreeSet<Integer>(new DescendingOrder());
ts.add(30);
ts.add(40);
ts.add(20);
ts.add(10);
Iterator<Integer> iter = ts.iterator();
while(iter.hasNext()) {
System.out.println(iter.next());
}
}
}