자바에서 컬렉션은 데이터를 저장하고 관리하는 자료 구조를 일반적으로 가리키는 용어다.
컬렉션은 다양한 데이터 요소를 담을수 있는 자료 구조를 의미하며, 이러한 자료 구조들은 Java Collections Framework를 통해 제공된다. Java Collection Framework는 데이터를 저장하고 관리하기 위한 다양한 인터페이스와 구현 클래스를 제공하여 개발자가 데이터를 효율적으로 다룰 수 있도록 도와준다.
자바 컬렉션들은 java.util 패키지를 import해야 사용할 수 있다.
순서가 있는 데이터를 저장하는 컬렉션으로, 중복된 요소를 허용한다. 예를 들어, ArrayList, LinkedList, Vector 등이 List의 구현 클래스다.
ArrayList: 배열 기반의 동적 배열을 사용하여 요소를 저장하는 List다. 요소의 추가, 삭제, 접근에 빠른 성능을 제공한다.
LinkedList: 이중 연결 리스트를 사용하여 요소를 저장하는 List다. 요소의 추가와 삭제가 빠르며, 중간에 요소를 삽입할 때 유용하다.
Vector: ArrayList와 유사하지만 스레드에 안전한 버전이다. 멀티스레드 환경에서 안전하게 사용할 수 있다.
import java.util.ArrayList;
import java.util.List;
public class ListExample {
public static void main(String[] args) {
// ArrayList 객체 생성
List<String> names = new ArrayList<>();
// 요소 추가
names.add("Alice");
names.add("Bob");
names.add("Charlie");
// 요소 접근
System.out.println("첫 번째 요소: " + names.get(0)); // "Alice"
// 요소 수정
names.set(1, "Eve");
System.out.println("수정된 요소: " + names.get(1)); // "Eve"
// 요소 삭제
names.remove(2);
System.out.println("삭제 후 요소 수: " + names.size()); // 2
// 모든 요소 출력
for (String name : names) {
System.out.println(name);
}
}
}
ArrayList를 사용하여 문자열을 저장하고 다양한 List 연산을 수행했다. List는 순서가 있으므로 인덱스를 사용하여 요소에 접근하거나 수정할 수 있으며, 반복문을 통해 모든 요소를 순회할 수 있다.
순서가 없고 중복을 허용하지 않는 데이터를 저장하는 컬렉션이다. 예를 들어, HashSet, LinkedHashSet, TreeSet 등이 Set의 구현 클래스다.
import java.util.HashSet;
import java.util.Set;
public class SetExample {
public static void main(String[] args) {
// HashSet 객체 생성
Set<String> colors = new HashSet<>();
// 요소 추가
colors.add("Red");
colors.add("Green");
colors.add("Blue");
// 중복된 요소는 추가되지 않음
colors.add("Red");
// 요소의 개수 확인
System.out.println("Set의 크기: " + colors.size()); // 3
// 요소 순회 및 출력
for (String color : colors) {
System.out.println(color);
}
// 요소 존재 여부 확인
boolean containsRed = colors.contains("Red");
System.out.println("Red가 포함되어 있는가? " + containsRed); // true
// 요소 삭제
colors.remove("Green");
System.out.println("Green 삭제 후 크기: " + colors.size()); // 2
}
}
HashSet을 사용하여 문자열을 저장하고 중복된 요소는 자동으로 제거된다. Set을 사용하면 고유한 요소만 저장할 수 있으며, 요소의 순서는 보장되지 않는다. Set은 주로 중복을 검사하거나 고유한 값만 저장해야 하는 경우에 사용된다.
Key-Value 쌍의 데이터를 저장하는 컬렉션으로, Key는 중복될 수 없다. 예를 들어, HashMap, LinkedHashMap, TreeMap 등이 Map의 구현 클래스다.
import java.util.HashMap;
import java.util.Map;
public class MapExample {
public static void main(String[] args) {
// HashMap 객체 생성
Map<String, Integer> scores = new HashMap<>();
// 요소 추가
scores.put("Alice", 95);
scores.put("Bob", 88);
scores.put("Charlie", 78);
// 중복된 키의 값을 덮어씀
scores.put("Alice", 92);
// 요소의 개수 확인
System.out.println("Map의 크기: " + scores.size()); // 3
// 값 조회
int aliceScore = scores.get("Alice");
System.out.println("Alice의 점수: " + aliceScore); // 92
// 요소 순회 및 출력
for (Map.Entry<String, Integer> entry : scores.entrySet()) {
String name = entry.getKey();
int score = entry.getValue();
System.out.println(name + ": " + score);
}
// 키 존재 여부 확인
boolean containsBob = scores.containsKey("Bob");
System.out.println("Bob의 키가 존재하는가? " + containsBob); // true
// 값 존재 여부 확인
boolean containsScore = scores.containsValue(78);
System.out.println("값 78이 존재하는가? " + containsScore); // true
// 요소 삭제
scores.remove("Charlie");
System.out.println("Charlie 삭제 후 크기: " + scores.size()); // 2
}
}
위 에제는 HashMap을 사용하여 문자열 키와 정수 값의 쌍을 저장하고 검색한다. Map은 각 키가 고유하므로 "Alice" 키가 중복으로 추가되면 이전 값이 덮어씌워진다. Map을 사용하면 키를 기반으로 값을 빠르게 검색하고 저장할 수 있으며, 요소의 순서는 보장되지 않는다.
Map은 키-값 쌍을 저장하고 관리하는데 사용되며, 주로 데이터의 빠른 검색이나 매핑에 활용된다.
큐 자료 구조를 구현하는 컬렉션으로, 요소를 추가하고 제거하는데 사용된다. 예를 들어, LinkedList는 Queue 인터페이스를 구현한 예다.
import java.util.LinkedList;
import java.util.Queue;
public class QueueExample {
public static void main(String[] args) {
// LinkedList를 사용한 Queue 객체 생성
Queue<String> queue = new LinkedList<>();
// 요소 추가 (enqueue)
queue.offer("Alice");
queue.offer("Bob");
queue.offer("Charlie");
// 큐의 크기 확인
System.out.println("큐의 크기: " + queue.size()); // 3
// 요소 조회 (peek)
String frontElement = queue.peek();
System.out.println("큐의 맨 앞 요소: " + frontElement); // Alice
// 요소 제거 (dequeue)
String removedElement = queue.poll();
System.out.println("큐에서 제거된 요소: " + removedElement); // Alice
// 큐의 크기 확인
System.out.println("큐의 크기: " + queue.size()); // 2
// 모든 요소 출력
while (!queue.isEmpty()) {
System.out.println("큐의 요소: " + queue.poll());
}
}
}
위 예제에서는 LinkedList를 사용하여 Queue를 생성하고, offer()
메서드로 요소를 추가하고 peek()
메서드로 맨 앞 요소를 조회한다. 그리고 poll()
메서드로 요소를 제거하면서 출력하고 큐의 크기를 확인한다.
Queue는 주로 대기열 처리, 태스크 스케줄링, 데이터의 순차 처리 등 다양한 상황에서 활용된다.
스택 자료구조를 구현하는 컬렉션으로, 요소를 추가하고 제거할 때 후입선출 방식을 따른다. 예를 들어 LinkedList도 Stack을 구현할 수 있다.
import java.util.Stack;
public class StackExample {
public static void main(String[] args) {
// Stack 객체 생성
Stack<String> stack = new Stack<>();
// 요소 추가 (push)
stack.push("Apple");
stack.push("Banana");
stack.push("Cherry");
// 스택의 크기 확인
System.out.println("스택의 크기: " + stack.size()); // 3
// 요소 조회 (peek)
String topElement = stack.peek();
System.out.println("스택의 맨 위 요소: " + topElement); // Cherry
// 요소 제거 (pop)
String poppedElement = stack.pop();
System.out.println("스택에서 꺼낸 요소: " + poppedElement); // Cherry
// 스택의 크기 확인
System.out.println("스택의 크기: " + stack.size()); // 2
// 모든 요소 출력
while (!stack.isEmpty()) {
System.out.println("스택의 요소: " + stack.pop());
}
}
}
스택은 주로 재귀 함수 호출 시 호출 스택을 모델링하거나, 브라우저의 뒤로 가기 기능, 역순 문자열 처리 등에 활용된다.
덱 자료 구조를 구현하는 컬렉션으로, 양쪽 끝에서 요소를 추가하거나 제거할 수 있다. ArrayDeque와 LinkedList가 Deque의 구현 클래스다.
import java.util.ArrayDeque;
import java.util.Deque;
public class DequeExample {
public static void main(String[] args) {
// Deque 객체 생성
Deque<String> deque = new ArrayDeque<>();
// 요소 추가 (큐의 뒤에 추가)
deque.offerLast("Apple");
deque.offerLast("Banana");
deque.offerLast("Cherry");
// 요소 추가 (큐의 앞에 추가)
deque.offerFirst("Orange");
// Deque 요소 출력 (큐의 처음부터 끝까지)
System.out.println("Deque의 요소:");
for (String element : deque) {
System.out.println(element);
}
// 큐의 앞에서 요소 제거
String firstElement = deque.pollFirst();
System.out.println("큐의 앞에서 제거한 요소: " + firstElement);
// 큐의 뒤에서 요소 제거
String lastElement = deque.pollLast();
System.out.println("큐의 뒤에서 제거한 요소: " + lastElement);
// Deque의 현재 크기 확인
System.out.println("Deque의 크기: " + deque.size());
}
}
위 코드에서는 ArrayDeque를 사용하여 Deque 객체를 생성하고, offerLast()
와 offerFirst()
메서드로 요소를 추가한다. 그 후 pollFirst()
와 pollLast()
메서드로 큐의 앞과 뒤에서 요소를 제거한다. 마지막으로 size()
메서드를 사용하여 Deque의 크기를 확인한다.
Deque는 큐와 스택의 특성을 모두 활용할 수 있기 때문에, 다양한 상황에서 유용하게 사용된다.
기존의 알고 있던 개념과 크게 다른 부분은 없는 것 같다. 하지만 인터페이스와 구현체라는 개념은 처음 접하기 때문에 다소 생소하다.
자바는 상속 개념을 많이 사용하기 때문에 상속을 제대로 이해하는 것이 중요한 것 같다.