🧩 BE
home

Java (컬렉션 기초)

JCF란 무엇인가요?
Java Collection Framework의 약자이며, 자료구조 및 알고리즘을 표준화한 인터페이스와 클래스들의 집합
→ List, Set, Map, Queue 등 다양한 컬렉션 자료형과 그 구현체 제공.
JCF의 계층 구조를 설명해 주세요.
Iterable이 최상위에 있고, 하위에 Collection이 있습니다. Collections은 List와 Set, Queue의 3가지 인터페이스로 나뉘어 있고, 각 인터페이스별 구현체가 하위에 존재하게 됩니다. List의 경우에는 ArrayList, LinkedList 등이 있고, Set은 HashSet 같은거, Queue는 우선순위 큐, 데크 등이 있습니다.
List 인터페이스는 무엇이고, 구현체의 종류는 무엇이 있나요?
순서가 보장되고, 중복 허용되는 선형 자료구조입니다.
ArrayList : 배열 기반, 빠른 접근, 느린 삽입/삭제
LinkedList : 노드 기반, 빠른 삽입/삭제, 느린 접근
Vector : ArrayList와 유사하지만, 동기화가 보장됨
ArrayList에 대해 설명해 주세요.
내부적으로 배열(Object[])을 사용
random access(인덱스 접근)가 빠름 → O(1)
중간 삽입/삭제는 느림 → O(n)
ArrayList는 어떻게 동적으로 사이즈가 늘어나나요?
내부적으로 Object 배열을 쓰기 때문에, 고정된 용량을 가집니다. 때문에 요소가 꽉차면 기존 길이에서 1.5배씩 자동으로 확장합니다.
확장 하면 새 배열 생성 후에 기존 데이터 복사하는 식으로 동작합니다.
새로운 배열로 참조 변경
LinkedList에 대해 설명해 주세요.
이중 연결 리스트(Double Linked List) 기반 자료구조
노드가 이전/다음 노드의 메모리 주소를 참조하는 식으로 동작
중간 삽입/삭제가 빠름 → O(1)
인덱스 접근은 느림 → O(n)
언제 ArrayList를 사용하고, 언제 LinkedList를 사용할까요?
ArrayList는 연속된 배열로 데이터를 저장하기 때문에 접근이 빨라서 요소가 적고 빠른 탐색이 필요할 때, ArrayList를 사용하고,
LinkedList는 노드 객체들이 서로 연결된 상태라, 삽입/삭제 시 연결만 바꾸면 되기 때문에 빈번하게 삽입/삭제가 일어날 경우에는 LinkedList를 쓰는게 좋습니다.
ArrayList와 Vector는 어떠한 차이가 있나요?
ArrayList와 Vector는 내부적으로 배열을 사용해 데이터를 저장한다는 점에서 유사하지만, 큰 차이점은 동기화 여부입니다.
ArrayList는 동기화를 지원하지 않아 단일 스레드 환경에서 빠른 성능을 제공하고,
Vector는 모든 메서드가 동기화되어 있어 멀티 스레드 환경에서 안전하지만 속도가 느릴 수 있습니다.
Stack과 Queue가 무엇인가요?
Stack: LIFO (후입선출)
push(), pop(), peek()
Deque 또는 LinkedList로 구현
Stack 메서드는 권장되지 않음
Queue: FIFO (선입선출)
offer(), poll(), peek()
LinkedList, PriorityQueue, ArrayDeque 등으로 구현
Set이 무엇이고, 구현 클래스가 무엇이 있는지 설명해 주세요.
내부적으로 hashCode() + equals()를 사용해 객체의 중복 여부 판단을 하여, 내부 요소 간의 중복이 없는 자료구조입니다.
→ 둘 다 같아야 동일 객체로 간주됨
HashSet
LinkedHashSet
TreeSet
Set에서 중복 요소를 어떻게 걸러내는지 설명해 주세요.
위 설명과 같음.
Map이 무엇이고, 구현 클래스가 무엇이 있는지 설명해 주세요.
Map은 키-값(key-value) 쌍을 저장하는 컬렉션입니다. 여기서 키는 중복이 불가능합니다.
HashMap: 가장 일반적, 해시 기반
LinkedHashMap: 순서 유지
TreeMap: 자동 정렬
Hashtable
HashMap은 어떻게 동작하나요?
Hash Map은 내부적으로 배열과 연결리스트(또는 트리)를 이용해 동작합니다.
1.
처음에 key를 저장할 때 hashCode()로 해시값을 만들고, 이 해시값으로 배열 인덱스를 계산합니다.
2.
그 인덱스에 해당하는 자리에 노드 삽입 (key-value)하고,
3.
충돌이 발생하면 LinkedList나 Tree로 변환해서 값을 저장합니다.
4.
탐색 시 hashCode + equals()로 key를 비교해서 정확한 데이터를 찾아냅니다.
HashMap의 최악의 시간 복잡도를 설명해 주세요.
보통 탐색/삽입/삭제 → O(1)
하지만 해시 충돌로 모든 key가 하나의 버킷(인덱스)에 몰리면 연결리스트 처럼 동작하게 돼서 선형 탐색때문에 → O(n)
Java 8 이후 버킷 내부의 요소 수가 8개 이상이면 레드 블랙 트리 구조로 개선 → O(log n)까지 성능이 보장됨
Map 인터페이스는 왜 Collection 인터페이스에 상속을 받지 않았나요?
Map은 키-값 쌍(Key-Value Pair)의 집합으로, 단순히 “요소들의 집합”이라는 Collection의 의미와는 구조적으로 다릅니다.
예를 들어 List, Set 등은 단일 값의 집합이고, Map은 (key, value) 쌍이므로 add()가 아닌 put() 메서드를 사용합니다.
개념적으로 값의 모음(Collection)“과 “키-값 매핑(Map)“은 다른 구조이기 때문에 자바의 설계상 따로 Collection을 상속하지 않습니다.
iterable과 iterator의 차이는 무엇인가요?
Iterable은 for-each 문에서 사용할 수 있게 만드는 인터페이스이고,
List, Set, Map.keySet()
Iterator는 실제 반복 로직을 담고 있는 객체입니다.
list.iterator()
Collection과 Collections의 차이는 무엇인가요?
Collection은 자바 컬렉션의 최상위 인터페이스로, 자료구조의 기본 동작을 정의합니다.
Collection<String> col = new HashSet<>()
반면 Collections는 컬렉션을 조작하는 정적 메서드 모음 유틸리티 클래스입니다.
Collections.sort(list)
Java에서 스레드를 만드는 방법을 설명해 주세요.
1.
Thread 클래스 상속
2.
Runnable 인터페이스 구현
3.
Callable<T> + Future 활용
4.
ExecutorService 통한 스레드 풀 관리
스레드 풀이란 무엇이고, 왜 사용할까요?
스레드 풀(Thread Pool)은 미리 생성된 스레드 집합을 재사용하는 구조로, 스레드 생성 비용을 줄이고 자원 낭비를 방지하는 데 목적이 있습니다.
매번 스레드 생성/삭제 비용 절감
과도한 스레드 생성으로 인한 OOM(Out of Memory) 방지
리소스 제한으로 안정적인 처리 가능
스프링과 같은 프레임워크에서는 스레드 풀의 스레드 개수를 수백 개 이상으로 운영합니다. 이는 Context Switching이 일어남에도 불구하고도 이런 선택을 내린 것인데, 왜 그럴까요?
동시 I/O 요청이나 비동기 이벤트 처리가 많은 경우, CPU 코어 수보다 훨씬 많은 스레드를 두어 I/O 대기 시간을 커버하는 것이 오히려 효율적입니다.
Web 서버(예: Spring WebMVC)는 대부분 Blocking I/O 모델이기 때문에,
수많은 요청이 대기 상태로 blocking되며 처리 흐름을 점유하진 않음
따라서 Context Switching 비용보다 Throughput 증가 효과가 더 큼