•
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 증가 효과가 더 큼