java 컬렉션 프레임워크
September 23, 2018
1. 컬렉션 프레임워크의 핵심 인터페이스 & 요약
- 컬렉션 : 데이터 그룹
- 프레임워크 : 표준화된 프로그래밍 방식
- 컬렉션 프레임워크 : 데이터 그룹을 저장하는 클래스들을 표준화한 설계
데이터를 다루는 데는 크게 3가지 타입이 존재한다.
- List : 순서O, 중복O
- ArrayList, LinkedList, Stack, Vector 등
- Set : 순서X, 중복X
- HashSet, TreeSet 등
- Map : Key와 Value의 쌍으로 이루어진 데이터집합. ex) 우편번호, Key는 중복X, Value는 중복O
- HashMap, TreeMap, Hashtable, Properties 등
요약
컬렉션 | 특징 |
---|---|
ArrayList | 배열기반. 순차적 추가삭제 빠름. 접근속도 빠름. 중간에 추가 삭제 느림. |
LinkedList | 연결기반. 중간에 추가 삭제 빠름. 접근속도 느림. 순차적 추가삭제 상대적으로 느림. |
HashMap | 배열과 연결이 결합된 상태. 추가, 삭제, 검색, 접근성 모두 뛰어남. 검색에 최고성능. |
TreeMap | 연결기반. 정렬과 검색에 적합. 검색성능은 HashMap보다 떨어짐 |
Stack | Vector를 상속받아 구현 |
Queue | LinkedList가 Queue인터페이스를 구현 |
2. ArrayList
- 가장 많이 사용되는 컬렉션 클래스
- Vector를 개선한 것
- 배열의 단점(배열 크기 수정 불가)을 개선하기 위해 만들어졌다. (out of bounds 에러 많이도 보았다.)
- 자동으로 배열의 크기를 늘려준다 -> 배열에 더 이상 저장할 공간이 없으면 보다 큰 배열을 생성해서 기존 배열에 저장된 내용을 복사하고 저장한다.
사용예
import java.util.*;
class ArrayListEx1{
public static void main(Stringp[] args){
ArrayList list1 = new ArrayList(4); // 처음 배열의 크기가 작아도 상관없음
list.add(new Integer(5)); // 리스트에 추가할때 add메서드 사용.
list.add(4); // 사실 요 안에 4는 컴파일러가 integer 객체로 바꿔준다. 덕분에 편하게 4만 쓸 수 있음. (AutoBoxing)
list.add(new Integer(2));
list.add(new Integer(0));
list.add(new Integer(1));
list.add(new Integer(3));
ArrayList list2 = new ArrayList(list1.subList(1,4)); // 1<= x <4 사이에 존재하는 객체를 반환
print(list1, list2);
Collections.sort(list1);
Collections.sort(list2); // list 오름차순 정렬
print(list1, list2);
System.out.println("list1.containsAll(list2):" + list1.containsAll(list2));
list2.add("B");
list2.add("C");
list2.add(3, "A");
print(list1, list2);
list2.set(3, "AA");
print(list1, list2);
// list1에서 list2와 겹치는 부분 남기고 나머지 삭제
System.out.println("list1.retainAll(list2):" + list1.retainAll(list2));
print(list1, list2);
// list2에서 list1에 포함된 객체 삭제
for(int i = list2.size()-1; i >= 0; i--){
if(list1.contains(list2.get(i)))
list2.remove(i);
}
print(list1, list2);
}
static void print(ArrayList list1, ArrayList list2) {
System.outprintln("list1:"+list1);
System.outprintln("list2:"+list2);
System.outprintln();
}
}
-
과제 : ArrayList의 add 메서드가 내부적으로 어떤 논리로 이루어지길래 자동으로 배열의 크기를 조절할 수 있는 걸까? p.591.
-
참고 : 배열을 새로만들고 복사하는 과정에서 처리시간이 많이 소요된다. 생성할때 여유있는 크기로 정하자.
3. LinkedList
-
불연속적으로 존재하는 데이터를 서로 연결한 형태로 구성
-
비순차적인 데이터 추가 삭제 빠르다.
- 데이터 추가 : 데이터 생성 1번, 연결 2번이면 끝남
- 데이터 삭제 : 데이터 연결만 바꾸면 끝.
-
Doubly-LinkedList : 양방향 (Ex : Volume up & down)
-
Doubly-Circular LinkedList : 양방향 + 마지막 요소와 첫번째 요소 연결 (Ex : Channel up & down)
4. Stack과 Queue
- Stack -> 순차적으로 데이터를 추가 삭제하기 때문에 ArrayList로 구현
- 저장 push
- 추출 pop
- Queue -> 삭제 할 때 첫번째 데이터를 삭제하므로, LinkedList로 구현
- 저장 offer
- 추출 poll
import java.util.*;
class StackQueueEx {
public static void main(String[] args){
Stack st = new Stack();
Queue q = new LinkedList(); // Queue인터페이스 구현체 LinkedLIst 사용 p.606 참고
st.push("0");
st.push("1");
st.push("2");
q.offer("0");
q.offer("1");
q.offer("2");
System.out.println("= Stack =");
while(!st.empty()){
System.out.println(st.pop());
}
System.out.println("= Queue =");
while(!q.isEmpty()){
System.out.println(q.poll());
}
// 결과를 예상해보자
}
}
5. Iterator
- 컬렉션에 저장된 데이터를 접근하는데 사용되는 표준화된 인터페이스
- Collection 인터페이스에 정의된 메서드 (즉 List, Set에도 Iterator가 포함되어있다)
- 요소체크 -> 읽음. 다 읽어오면 재사용 안된다. 다시 얻어와야 한다.
import java.util.*;
class IteratorEx1 {
public static void main(String[] args){
Collection list = new ArrayList(); // 다른 컬렉션으로 변경할 땐 여기만 바꾸면된다. ArrayList에만 있는 메서드를 사용하는 게 아니라면 Collection 타입을 쓰는 편이 낫다.
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");
Iterator it = list.iterator(); // (참조변수 it을 가지고 list를 접근할거야)
while(it.hasNext()){ // boolean -> 읽어올 요소가 있으면 true
Object obj = it.next(); // 다음요소를 읽어온다
System.out.println(obj);
// System.out.println(it.next());
}
}
}
6. Arrays
- 배열을 다룰 때 유용한 메서드가 있다
- 특히 배열 복사할 때! 정렬할 때!, 검색할 때!
- Arrays.copyof()
- sort()
- binarySearch()
7. Comparator와 Comparable
- 정렬방법
- 기본 오름차순 정렬하려면 Comparable
- 다른 기준으로 정렬하려면 Comparator 구현
- Comparator 구현
- public int compare(Object o1, Object o2) 메서드 만들기
- compare()의 매개변수가 Object타입이기 때문에 compareTo()를 바로 호출할 수 없으므로 먼저 Comparable로 형변환 해야한다
- 메서드 안에 정렬기준식 쓴다
import java.util.*;
class ComparatorEx{
public static void main(String[] args){
String[] strArr = { "cat", "Dog", "lion", "tiger" };
Arrays.sort(strArr); // Comparable구현에 의한 정렬
System.out.println(Arrays.toString(strArr));
Arrays.sort(strArr, String.CASE_INSENSITIVE_ORDER); // 대소문자 구분안함
System.out.println(Arrays.toString(strArr));
Arrays.sort(strArr, new Descending()); // 새로운 정렬 기준. Descending 클래스를 만들고 Comparator 인터페이스 구현
System.out.println(Arrays.toString(strArr));
}
}
class Descending implements Comparator{
public int compare(Object o1, Object o2){
if(o1 instanceof Comparable && o2 instanceof Comparable){
Comparable c1 = (Comparable)o1;
Comparable c2 = (Comparable)o2;
return c2.compareTo(c1) ; // 역순정렬
}
return -1;
}
}
실행결과
[Dog, cat, lion, tiger]
[cat, Dog, lion, tiger]
[tiger, lion, cat, Dog]
8. HashSet(참고)
9. TreeSet
- 범위 검색과 정렬에 유리한 컬렉션 클래스
- Binary Search Tree(이진탐색트리)로 구현
- 전위, 중위, 후위. 중위순회하면 오름차순 정렬
10. HashMap과 Hashtable
- HashMap은 Hashtable의 새로운 버전
- Id, Password처럼 연관된 데이터는 하나의 배열로 다루는 것이 바람직하다.
- Id와 Password를 하나의 Entry로 저장한다.
- Id(Key)는 중복이면 안된다.
- 해싱(Hashing)을 사용하여 많은양의 데이터 검색에 유리
포프킴이 면접으로 Hashtable을 구현해보라는 문제를 종종 낸다고 한다. 이유는 여기 : 포프킴-Hashtable은 프로그래머의 기본기
고로 예제 하나 풀어보자(Hashtable을 구현한 것은 아니고 사용만 한 것)
import java.util.*;
class HashMapEx1{
public static void main(String[] args){
HashMap map = new HashMap();
map.put("myId", "1234"); // Key와 Value를 HashMap에 저장
map.put("asdf", "1111");
map.put("asdf", "1234"); // Key가 중복인 경우 덮어씌여진다
Scanner s = new Scanner(System.in);
while(true) {
System.out.println("id와 password를 입력해주세요");
System.out.print("id :");
String id = s.nextLine().trim();
System.out.print("password :");
String password = s.nextLine().trim();
System.out.println();
if(!map.containsKey(id)){
System.out.println("입력하신 id는 존재하지 않습니다." + " 다시 입력해주세요.");
continue;
} else {
if(!(map.get(id)).equals(password)){
System.out.println("비밀번호가 일치하지 않습니다." + " 다시 입력해주세요.");
} else {
System.out.println("id와 비밀번호가 일치합니다.");
break;
}
}
}
}
}