학습 개요
- 컬렉션이란 여러 원소를 저장하고 관리하는 자료구 조임
- JCF는 컬렉션을 관리하기 위한 클래스와 인터페이스를 제공하는 통합 프레임워크임
Collection
,Set
,List
,Queue
,Map
등의 인터페이스와 그것을 구현한HashSet
,ArrayList
,LinkedList
,HashMap
등의 클래스 사용법을 학습함
학습 목표
- JCF의 기본 구조를 설명할 수 있음
HashSet
클래스를 사용하여 프로그램을 작성할 수 있음ArrayList
와LinkedList
클래스의 차이를 설명할 수 있음HashMap
클래스를 사용하여 복잡한 자료를 관리할 수 있음
강의록
JCF
컬렉션이란
- 여러 원소를 하나의 그룹으로 묶어 관리하기 위한 자료 구조
- JCF는 컬렉션 즉, 데이터 목록을 관리하기 위한 인터페이스와 클래스의 모음
- JCF(Java Collections Framework)
- 컬렉션을 표현하고 다루기 위한 통합된 프레임 워크
- 클래스와 인터페이스의 집합
- 컬렉션을 다양한 방식으로 저장, 정렬, 검색, 수정하는 도구를 제공
- 컬렉션을 일관 된 방법으로 다룰 수 있음
- 표준화 된 인터페이스
- 컬렉션을 다루기 위한 기능을 표현
- 어떻게 표현되는 지와 상관없이 일관성 있게 다룸
- 클래스
- 인터페이스를 구현한 클래스를 제공
- 표준화 된 인터페이스
- 컬렉션을 표현하고 다루기 위한 통합된 프레임 워크
JCF의 구조
JCF의 인터페이스
Set
- 데이터의 순서는 의미가 없으며 중복을 허용하지 않는 자료 구조
List
- 중복을 허용하고 순서가 있는 자료 구조
Queue
List
와 유사하나 원소의 삽입/삭제가 FIFO 방식
Map
- 원소가
<key, value>
의 형태이며 키는 유일해야 함
- 원소가
JCF의 인터페이스와 클래스
java.util
패키지에 포함되며 제네릭 타입다루는 자료의 유형을 지정해야 함
구분 Set List Queue Map 해시 테이블 HashSet
HashMap
배열 ArrayList
,Vector
,Stack
연결 리스트 LinkedList
LinkedList
해싱 + 연결 리스트 LinkedHashSet
LinkedHashMap
정렬 SortedSet
SortedMap
트리 TreeSet
TreeMap
컬렉션 객체의 선언
변수 선언은 해당 인터페이스 유형으로, 객체 생성은 인터페이스를 구현하는 클래스를 사용
1
Set<Integer> set = new HashSet<>();
1
List<Integer> list = new ArrayList<>();
1
List<Integer> list = new LinkedList<>();
1
Queue<Integer> queue = new LinkedList<>();
1
Map<String, Integer> map = new HashMap<>();
Collection<E>
인터페이스
Set
,List
,Queue
에서 공통으로 지원해야 하는 기능을 정의원소의 삽입과 삭제 메소드
메소드 설명 boolean add(E e)
주어진 요소를 현재 컬렉션에 추가함, 성공적으로 추가되면 true를 리턴 boolean addAll(Collection<? extends E> c)
주어진 컬렉션의 모든 요소를 현재 컬렉션에 추가 boolean remove(Object o)
주어진 요소를 컬렉션에서 제거 boolean removeAll(Collection<?> c)
주어진 컬렉션에 포함된 모든 요소를 현재 컬렉션에서 제거 boolean retainAll(Collection<?> c)
현재 컬렉션의 요소 중 주어진 컬렉션에 있는 요소만 남김 void clear()
컬렉션의 모든 요소를 제거하여 비움 원소 탐색 메소드
메소드 설명 boolean contains(Object o)
현재 컬렉션이 주어진 요소를 가지고 있으면 true를 리턴 boolean containsAll(Collection<?> c)
현재 컬렉션에 주어진 컬렉션의 모든 요소가 포함되어 있으면 true를 리턴 boolean isEmpty()
현재 컬렉션이 빈 컬렉션이면 true를 리턴 기타 메소드
메소드 설명 int size()
현재 컬렉션에 포함된 요소의 개수를 리턴 int hashCode()
현재 컬렉션의 해시 코드값을 리턴 Object[] toArray()
현재 컬렉션을 객체의 배열로 변환하여 리턴 Iterator<E> iterator()
Iterator 객체를 리턴 boolean equals(Object)
두 컬렉션이 같은 요소를 같은 순서로 포함하면 true를 리턴
HashSet
, ArrayList
, LinkedList
클래스
HashSet
클래스 예제
HashSet
클래스 사용 예1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
import java.util.*; public class Main { public static void main(String args[]) { Set<String> set = new HashSet<String>(); // HashSet 객체를 생성 // HashSet에 문자열 값 추가 set.add("one"); set.add("two"); set.add("three"); set.add("four"); System.out.println(set.add(new String("one"))); // HashSet은 중복을 허용하지 않으므로 이미 존재하는 "one"을 추가하지 않음 System.out.println(set.size()); // HashSet의 현재 크기를 출력 System.out.println(set.contains("four")); // HashSet이 "four"라는 요소를 포함하고 있는지 확인 System.out.println(set.contains("one")); // HashSet이 "one"이라는 요소를 포함하고 있는지 확인 System.out.println(set.contains(new String("one"))); // "one"이라는 값이 존재하는지 확인 set.remove("four"); // "four"라는 요소 제거 set.remove(new String("one")); // "one"이라는 문자열 제거 System.out.println(set.size()); set.clear(); // HashSet의 모든 요소를 제거 System.out.println(set.size()); // HashSet의 현재 크기를 출력 (모든 요소가 삭제되었으므로 크기는 0) } } // false // 4 // true // true // true // 2 // 0
ArrayList<E>
클래스
List
인터페이스를 구현한 클래스- 크기 조절이 가능한 배열로 구현
- 같은 자료가 중복 될 수 있으며, 입력 된 순서대로 관리 됨
- 특정 위치의 자료를 참조하기 위해 첨자를 사용할 수 있음
List
인터페이스를 살펴봐야 함- 주요 메소드
boolean add(E e)
- 원소를 맨 뒤에 삽입
void add(index, E element)
- 해당 위치에 원소를 삽입
boolean remove(Object o)
- 삭제에 성공하면 true를 리턴
E remove(int index)
- 삭제 되는 원소를 리턴
E get(int index)
- 해당 위치의 원소를 리턴
E set(int index, E element)
- 기존 원소를 리턴
int indexOf(Object o)
- 리스트 내에서 지정된 객체가 처음으로 등장하는 인덱스 리턴
1 2 3 4 5 6 7
List<String> list = new ArrayList<>(); list.add("apple"); list.add("banana"); list.add("apple"); System.out.println(list.indexOf("apple")); // 0 System.out.println(list.indexOf("grape")); // -1
int lastIndexOf(Object o)
- 리스트 내에서 지정된 객체가 마지막으로 나타난 위치의 인덱스 리턴
1 2 3 4 5 6 7
List<String> list = new ArrayList<>(); list.add("apple"); list.add("banana"); list.add("apple"); System.out.println(list.lastIndexOf("apple")); // 2 System.out.println(list.lastIndexOf("grape")); // -1
List<E> subList(int from, int to)
- 지정된 범위(
from
부터to
전까지)의 리스트(서브 리스트)를 반환
1 2 3 4 5 6 7 8 9 10
List<String> list = new ArrayList<>(); list.add("apple"); list.add("banana"); list.add("cherry"); List<String> subList = list.subList(0, 2); // "apple", "banana" System.out.println(subList); // [apple, banana] list.set(1, "blueberry"); // 원본 리스트 변경 시 서브리스트도 반영됨 System.out.println(subList); // [apple, blueberry]
- 지정된 범위(
ListIterator<E> listIterator()
- 리스트 내의 요소를 양방향(앞으로 또는 뒤로)으로 탐색할 수 있는 리스트 반복 자 반환
1 2 3 4 5 6 7 8 9 10 11 12
List<String> list = new ArrayList<>(); list.add("apple"); list.add("banana"); // 리스트 반복자를 생성 ListIterator<String> it = list.listIterator(); // 다음 요소 탐색 while (it.hasNext()) { System.out.println(it.next()); } // apple, banana
ListIterator<E> listIterator(int index)
- 특정 인덱스(index)에서 시작하는 리스트 반복 자를 반환
- 인덱스가 유효하지 않을 경우
IndexOutOfBoundsException
이 발생
1 2 3 4 5 6 7 8 9 10 11 12
List<String> list = new ArrayList<>(); list.add("apple"); list.add("banana"); list.add("cherry"); // 1번 인덱스부터 시작하는 Iterator 생성 ListIterator<String> it = list.listIterator(1); while (it.hasNext()) { System.out.println(it.next()); } // banana, cherry
ArrayList
클래스 예제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import java.util.*;
public class Main {
public static void main(String args[]) {
List<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
list.add(1, "one");
list.add("five");
System.out.println(list.size());
System.out.println(list.indexOf("one"));
System.out.println(list.get(2));
System.out.println(list.lastIndexOf("one"));
System.out.println(list.set(3, "four"));
System.out.println(list.remove(4));
System.out.println(list.remove("one"));
}
}
// 5
// 0
// two
// 1
// three
// five
// true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import java.util.*;
public class Main {
public static void main(String args[]) {
List<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
list.add("four");
list.add("five");
// for 구문을 이용한 자료 탐색
for (int i = 0; i < list.size(); i++)
System.out.println(list.get(i));
// 향상된 for 구문을 이용한 자료 탐색
for (String s : list)
System.out.println(s);
// Iterator 인터페이스를 이용한 자료 탐색
Iterator<String> it = list.iterator();
while (it.hasNext())
System.out.println(it.next());
}
}
// one
// two
// three
// four
// five
// one
// two
// three
// four
// five
// one
// two
// three
// four
// five
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import java.util.*;
import java.util.function.Consumer;
public class Main {
public static void main(String args[]) {
List<String> list = new ArrayList<String>();
list.add("one");
list.add("three");
list.add("two");
list.add(1, "one");
// Consumer 인터페이스를 활용해 accept 메서드를 직접 구현한 익명 클래스
Consumer<String> con1 = new Consumer<>() {
// Consumer 인터페이스의 추상 메서드 accept를 구현
public void accept(String t) {
System.out.println(t); // 각 요소를 처리
}
};
// 리스트의 각 요소에 대해 con1의 accept 메서드를 실행
list.forEach(con1);
// 람다식을 사용하여 Consumer의 동작 구현
Consumer<String> con2 = t -> System.out.println(t);
// 리스트의 각 요소를 처리하며 출력
list.forEach(con2);
// 리스트의 각 항목에 대해 직접 람다 표현식 전달
list.forEach(t -> System.out.println(t));
}
}
// one
// one
// three
// two
// one
// one
// three
// two
// one
// one
// three
// two
Iterator<E>
인터페이스
- 컬렉션에 저장 된 원소를 차례대로 다룰 수 있음
- 다음 메소드를 제공
boolean hasNext()
- 순회할 다음 요소가 있으면
true
리턴
- 순회할 다음 요소가 있으면
E next()
- 다음 요소를 리턴하고, 커서를 다음 위치로 이동
void remove()
next()
로 반환된 가장 최근 요소를 컬렉션에서 삭제
컬렉션
HashSet
,ArrayList
,LinkedList
등에서Iterator
객체를 리턴하는iterator()
메소드를 사용할 수 있음1 2 3 4 5 6
List<String> list = new ArrayList<String>(); Iterator<String> it = list.iterator(); // Iterator 객체 얻기 while (it.hasNext()) // 다음 요소가 있는지 확인 System.out.println(it.next()); // 다음 요소 가져와 출력
LinkedList
클래스
ArrayList
와 마찬가지로List
인터페이스를 구현한 클래스- 앞의 예제에서
ArrayList
를LinkedList
로 바꿔도 됨
- 앞의 예제에서
- 스택 자료 구조에서 필요한 메소드도 제공함
앞에서 넣거나 삭제
1
void push(E)
1
E pop()
Queue
인터페이스도 구현함뒤에서 원소를 추가함
1
boolean add(E)
1
boolean offer(E)
앞의 원소를 삭제하고 리턴함
1
E poll()
1
E remove()
앞의 원소를 읽음
1
E peek()
1
E element()
LinkedList
를 이용하여 큐를 구현한 예제
LinkedList
클래스로 큐 구현하기1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
import java.util.*; public class Main { public static void main(String args[]) { LinkedList<String> queue = new LinkedList<String>(); queue.offer("one"); queue.offer("two"); queue.offer("three"); queue.offer("four"); String s = queue.poll(); while (s != null) { System.out.println(s); s = queue.poll(); } } } // one // two // three // four
HashMap
클래스
Map<K, V>
인터페이스
- (key, value)로 이루어진 원소로 구성되는 컬렉션을 다루기 위한 인터페이스
- key는 중복되지 않으며, 하나의 key에 하나의 value만 대응됨
- 원소들의 순서는 중요하지 않음
주요 메소드
메소드 설명 V put(K key, V value)
맵에 <키, 값> 매핑을 추가, 키가 존재하면 값이 변경됨 V get(Object key)
맵에서 키와 매핑 된 값을 리턴, 없으면 null을 리턴 V remove(Object key)
키에 대응하는 매핑을 제거하고 값을 리턴, 없으면 null boolean containsKey(Object key)
지정된 키가 맵에 있으면 true를 리턴 Collection<V> values()
맵에 존재하는 값들로 구성된 컬렉션을 리턴 Set<K> keySet()
맵에 존재하는 키들로 구성된 Set 객체를 리턴
HashMap
클래스
- 해싱을 이용하여
Map
인터페이스를 구현한 클래스- 자료 탐색 방법이
ArrayList
나LinkedList
클래스와 다름
- 자료 탐색 방법이
복잡한 자료 관리(교재의 예)
복잡한 자료 관리 – HashMap
클래스 예제
성적 관리 프로그램
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
Map<String, Integer> lectures; // 학생별 과목 점수를 저장할 Map 생성 선언 Map<String, Map<String, Integer>> scores = new HashMap<>(); // String, Map<String,Integer>로 타입 명시 List<String> names = new ArrayList<String>(); // 학생의 이름을 담을 리스트 생성 names.add("김철수"); names.add("이영희"); Iterator<String> it = names.iterator(); // 이름 리스트를 순회하기 위해 Iterator 생성 // 이름 리스트의 각 학생에 대해 과목 점수를 설정 while (it.hasNext()) { String name = it.next(); // 다음 이름 가져오기 if (name.equals("김철수")) { lectures = new HashMap<String, Integer>(); // 새로운 과목 점수를 저장할 HashMap 생성 lectures.put("국어", 100); lectures.put("영어", 95); lectures.put("수학", 80); scores.put(name, lectures); // 전체 점수 Map(scores)에 추가 } else { lectures = new HashMap<String, Integer>(); lectures.put("국어", 90); lectures.put("영어", 95); lectures.put("수학", 95); scores.put(name, lectures); } } Iterator<String> it2 = names.iterator(); while (it2.hasNext()) { String name = it2.next(); System.out.println(name); System.out.print("국어 : "); System.out.println(scores.get(name).get("국어")); // scores.get(name)으로 Map<String, Integer> 얻고 다시 get("과목") System.out.print("영어 : "); System.out.println(scores.get(name).get("영어")); System.out.print("수학 : "); System.out.println(scores.get(name).get("수학")); System.out.println(); } // 김철수 // 국어 : 100 // 영어 : 95 // 수학 : 80 // 이영희 // 국어 : 90 // 영어 : 95 // 수학 : 95
학습 정리
- 컬렉션은 여러 원소를 저장하고 관리하는 객체를 통칭하는 용어이며, JCF는 컬렉션을 효율적으로 다루기 위한 API를 제공하는 프레임워크임
Set
은 원소의 순서에 의미가 없고 중복을 허용하지 않는 컬렉션을 다루기 위한 인터페이스임List
와Queue
는 자료의 중복을 허용하고 순서에 의미가 있는 컬렉션을 관리하기 위한 인터페이스임Queue
는 FIFO 방식으로 자료를 관리하는 인터페이스임
Map
인터페이스는 <키, 값>의 쌍으로 구성되는 자료의 묶음을 관리하는 메소드를 제공함LinkedList
클래스는List
인터페이스와Queue
인터페이스를 모두 구현한 클래스이며, 스택 자료구조에서 필요한 메소드도 제공함
연습 문제
ArrayList
클래스에 관한 설명으로 적당하지 않은 것은?a. 같은 자료를 중복으로 저장할 수 없다.
ArrayList
클래스에 대한 설명으로 적당한 것List
인터페이스를 구현한 클래스임- 여러 원소를 저장하기 위해 내부적으로 배열을 사용함
- 원소의 순서가 의미를 가짐
- 같은 자료를 중복으로 저장할 수 있음
(key, value) 형태의 원소로 구성되는 자료 묶음을 다루기 위한 인터페이스나 클래스가 아닌 것은?
a.
HashSet
- (key, value) 형태의 원소로 구성되는 자료 묶음을 다루기 위한 인터페이스나 클래스
HashMap
Hashtable
Map
- (key, value) 형태의 원소로 구성되는 자료 묶음을 다루기 위한 인터페이스나 클래스
LinkedList<E>
를 이용하여 큐 자료구조를 구현할 때, 자료를 추가하는 메소드와 삭제하는 메소드는 무엇인가?a. 추가 시
boolean offer(E)
,boolean add(E)
, 삭제 시E remove()