컬렉션의 사전적 의미는 요소를 수집해서 저장하는 것
프로그래밍을 하다보면 다수개의 객체를 저장해 두고 필요할 때 마다 꺼내서 사용하는 경우
가장 간단한 방법 - 배열
배열은 쉽게 생성하고 사용할 수 있지만, 저장할 수 있는 객체 수가 배열을 생성할 때 결정되기 때문에 불특정 다수의 객체를 저장하기에는 문제가 있다.
이때 자바는 배열의 이런 문제점을 해결하고, 널리 알려져 있는 자료구조를 바탕으로 객체들을 효율적으로 추가,삭제,검색할 수 있도록 java.util 패키지에 컬렉션과 관련된 인터페이스와 클래스들을 포함시켜 놓았는데 이들을 총칭해서 컬렉션 이라 부른다.
List와 Set은 객체를 추가, 삭제, 검색하는 방법에 많은 공통점이 있는데 이 인터페이스들의 공통된 메소드만 모아 Collection 인터페이스로 정의해두고 있다.
Map은 키(Key)와 값(Value)을 하나의 쌍으로 묶어서 관리하는 구조로 되어 있지만 List와 Set과는 자료구조의 사용 방법이 전혀 다름.
LIst, Set, Map의 특징
Set의 중복 저장 불가가 중요한 부분
List
List 컬렉션은 객체를 일렬로 늘어놓은 구조
배열도 같은 특징을 가지고 있지만, 배열은 선언 시점에 저장할 수 있는 크기가 결정이 되기 때문에 명확하지 않은 경우에 선언하기가 어려운 단점이 있다.
그걸 보완한, 자료형의 개수가 계속 변하는 상황에서 유리한 자료구조 형태가 바로 List 이다.
기능 | 메소드 | 설명 |
---|---|---|
객체 추가 | boolean add(E e) | 주어진 객체를 맨 끝에 추가 |
void add(int index, E element) | 주어진 인덱스에 객체를 추가 | |
set(int index, E element) | 주어진 인덱스에 저장된 객체를 주어진 객체로 바꿈 | |
객체 검색 | boolean contains(Object o) | 주어진 객체가 저장되어있는지 여부 |
E get(int index) | 주어진 인덱스에 저장된 객체를 리턴 | |
isEmpty() | 컬렉션이 비어있는지 여부 | |
int size() | 저장되어 있는 전체 객체 수 리턴 | |
객체 삭제 | void clear() | 저장된 모든 객체를 삭제 |
E remove(int index) | 주어진 인덱스에 저장된 객체를 삭제 | |
boolean remove(Object o) | 주어진 객체를 삭제 |
시간 복잡도 : 효율성
ArrayList - O(N), 상수시간복잡도. 최악의 경우
LinkedList - O(1), 상수시간복잡도. 상당히 빠름
ArrayList
ArrayList 객체 삭제 시 매커니즘
ArrayList는 내부 배열의 객체를 인덱스로 관리
LinkedList는 인접 참조를 링크하여 체인형식으로 관리
삽입과 삭제등 내부 배열 객체의 수정이 잦은 작업에 용이
package chap11.list;
import java.util.*; // util 내에 있어서 전체 임포트
public class ArrayListExample {
public static void main(String[] args) {
// ArrayList 값 추가
List<String> list = new ArrayList<>(); // 디폴트로 10개의 공간이 있는 배열이 할당됨. 이때 객체를 추가하면 추가한 갯수만큼 배열 생성
list.add("Java");
list.add("Spring");
list.add("Servlet/JSP");
list.add("DBMS");
list.add("JPA");
// 추가된 값 총 개수
System.out.println("총 개수 : " + list.size());
// 값 순회하면서 출력
for (int i = 0; i < list.size(); i++) {
System.out.println("\t" + i + " : " + list.get(i));
}
// 값 삭제
list.remove(2);
list.remove(2);
list.remove("Java");
// 총 개수 출력
System.out.println("총 개수 : " + list.size());
// 향상된 for문으로 순회하면서 값 출력
for (String element : list) {
System.out.println("\t" + list + " : " + element);
}
}
}
package chap11.list;
import java.util.*;
public class LinkedListExample {
public static void main(String[] args) {
// List의 구현체여서 이름만 바꿔줘도 사용 가능
List<String> list = new LinkedList<>();
list.add("Java");
list.add("Spring");
list.add("Servlet/JSP");
list.add("DBMS");
list.add("JPA");
// 추가된 값 총 개수
System.out.println("총 개수 : " + list.size());
// 값 순회하면서 출력
for (int i = 0; i < list.size(); i++) {
System.out.println("\t" + i + " : " + list.get(i));
}
// 값 삭제
list.remove(2);
list.remove(2);
list.remove("Java");
// 총 개수 출력
System.out.println("총 개수 : " + list.size());
// 향상된 for문으로 순회하면서 값 출력
for (String element : list) {
System.out.println("\t" + list + " : " + element);
}
}
}
package chap11.list;
import java.util.*;
public class LinkedListExample {
public static void main(String[] args) {
List<String> arrayList = new ArrayList<>();
List<String> linkedList = new LinkedList<>();
long startTime;
long endTime;
startTime = System.nanoTime();
for (int i = 0; i < 10000; i++) {
arrayList.add(0, String.valueOf(i));
}
endTime = System.nanoTime();
System.out.println("ArrayList 걸린시간: " + (endTime - startTime) + "ns");
startTime = System.nanoTime();
for (int i = 0; i < 10000; i++) {
linkedList.add(0, String.valueOf(i));
}
endTime = System.nanoTime();
System.out.println("LinkedList 걸린시간: " + (endTime - startTime) + "ns");
}
}
// 결과
ArrayList 걸린시간: 3211300ns
LinkedList 걸린시간: 1221000ns
List 컬렉션은 저장 순서를 유지하지만, Set 컬렉션은 저장 순서가 유지되지 않음.
또한 객체를 중복해서 저장할 수 없다는 큰 특징이 있습니다.
기능 | 메소드 | 설명 |
---|---|---|
객체 추가 | boolean add(E e) | 주어진 객체를 저장, 객체가 성공적으로 저장되면 true를 리턴하고 중복 객체면 false를 리턴 |
객체 검색 | boolean contains(Object o) | 주어진 객체가 저장되어 있는지 여부 |
isEmpty() | 컬렉션이 비어 있는지 조사 | |
Iterator iterator() | 저장된 객체를 한 번씩 가져오는 반복자 리턴 | |
int size() | 저장되어 있는 전체 객체 수 리턴 | |
객체 삭제 | void clear() | 저장된 모든 객체를 삭제 |
boolean remove(Object o) | 주어진 객체를 삭제 |
Iterator(반복자) 인터페이스에 선언된 메소드
Set<String> set = ...;
Iterator<String> iterator = set.iterator();
리턴 타입 | 메소드명 | 설명 |
---|---|---|
boolean | hasNext() | 가져올 객체가 있으면 true를 리턴하고 없으면 false를 리턴합니다 |
E | next() | 컬렉션에서 하나의 객체를 가져옵니다 |
void | remove() | Set 컬렉션에서 객체를 제거합니다 |
Set 인터페이스는 중복처리를 한다. 중복인 객체는 저장하지 않는다.
해당 내용의 매커니즘
기능 | 메소드 | 설명 |
---|---|---|
객체추가 | V put(K key, V value) | 주어진 키와 값을 추가, 저장되면 값을 리턴 |
객체검색 | boolean containsKey(Object key) | 주어진 키가 있는지 여부 |
boolean containsValue(Object value) | 주어진 값이 있는지 여부 | |
Set(Map.Entry<K,V>> entrySet() | 키와 값의 쌍으로 구성된 모든 Map.Entry 객체를 Set에 담아서 리턴 | |
V get(Object key) | 주어진 키가 있는 값을 리턴 | |
boolean isEmpty() | 컬렉션이 비어 있는지 여부 | |
Set keySet() | 모든 키를 Set 객체에 담아서 리턴 | |
int size() | 저장된 키의 총 개수 리턴 | |
Collection values() | 저장된 모든 값을 Collection에 담아서 리턴 | |
객체삭제 | vold clear() | 모든 Map.Entry(키와 값)를 삭제 |
V remove(Object key) | 주어진 키와 일치하는 Map.Entry를 삭제하고 값을 리턴 |
Map<String, Integer> map = ...;
map.put("홍길동", 30); // 객체 추가
int score = map.get("홍길동"); // 객체 찾기
map.remove("홍길동"); // 객체 삭제
Map<K, V> map = ...;
Set<K> keySet = map.keySet();
Iterator<K> keyIterator = keySet.iterator();
while(keyIterator.hasNext()) {
K key = keyIterator.next();
V value = map.get(key);
}
Set<Map.Entry<String, Object>> entries = map.entrySet();
for (Map.Entry<String, Object> entry : entries) {
String key = entry.getKey();
Object value = entry.getValue();
}
후입선출 (LIFO : Last In First Out)
선입선출 (FIFIO : First In First Out)
리턴 타입 | 메소드 | 설명 |
---|---|---|
E | push(E item) | 주어진 객체를 스택에 넣는다 |
E | peek() | 스택의 맨 위 객체를 가져온다. 객체를 스택에서 제거하지 않는다. |
E | pop() | 스택의 맨 위 객체를 가져오고, 객체를 스택에서 제거한다. |
Stack<E> stack = new Stack<E>(); // 스택 객체 생성
리턴 타입 | 메소드 | 설명 |
---|---|---|
boolean | offer(E e) | 주어진 객체를 넣는다. |
E | peek() | 객체 하나를 가져온다. 객체를 큐에서 제거하지 않는다. |
E | poll() | 객체 하나를 가져온다. 객체를 큐에서 제거한다. |
Queue<E> queue = new LinkedList<E>(); // 큐 객체 생성