모던 자바 인 액션
컬렉션 API, 리팩터링, 테스팅, 디버깅, 람다를 이용한 도메인 전용 언어에 대해 학습합니다.
Chapter8 - 컬렉션 API 개선
Java 8과 그 이후 버전에서 도입된 컬렉션 API의 주요 개선 사항과 새로운 기능을 정리한다.
컬렉션 팩토리
Java 9에서 도입된 컬렉션 팩토리 메서드는 불변 컬렉션을 쉽게 생성할 수 있다.
- 리스트 팩토리 :
List.of()
- 집합 팩토리 :
Set.of()
- 맵 팩토리 :
Map.of()
기존 방식보다 간결하며, 생성된 컬렉션은 변경 불가(immutable)하다.
1 |
|
특징
- 컬렉션은 불변(Immutable)하여 요소를 추가하거나 삭제가 불가능
null
값을 허용하지 않음
리스트와 집합 처리
removeIf
: Predicate를 만족하는 요소를 제거replaceAll
: UnaryOperator 함수를 이용하여 요소를 바꿈UnaryOperator
: 입력과 출력이 같은 타입인 연산
sort
: List 인터페이스에서 제공하는 기능으로 리스트를 정렬
맵처리
forEach
: Map에서 키와 값을 반복하며, BiConsumer를 인수로 받는 메서드를 지원한다.BiConsumer
: 두 개의 입력값(매개변수)을 받아 연산을 수행하지만 결과를 반환하지 않는 연산
- 정렬 메서드 : 아래 두개의 유틸리티 메서드를 이용하여, 값 또는 키를 기준으로 정렬할 수 있다.
- Entry.comparingByValue
- Entry.comparingByKey
getOrDefault
: 첫 번째 인수로 키를, 두 번째 인수로 기본값을 받아 맵에 키값이 존재하지 않으면 두 번째 인수인 기본값을 반환한다.
계산 패턴
Map의 키와 값을 기반으로 새 값을 동적으로 생성하거나 변경한다.
computeIfAbsent
: 키가 없으면 새 값을 계산하여 추가computeIfPresent
: 키가 존재할 경우, 새 값을 계산하여 교체compute
: 키가 존재하거나 없거나 상관없이 값을 계산(값이 null이면 삭제)
1 |
|
교체 패턴
맵에 이미 존재하는 값을 조건에 따라 변경하거나 삭제한다.
replace
: 특정 키의 값이 존재하면 새 값으로 교체replaceAll
: 모든 키-값 쌍에 대해 함수를 적용해 값을 교체
1 |
|
합침
맵의 기존 값과 새 값을 조건에 따라 병합한다.
merge
: 키가 존재하면 기존 값과 새 값을 병합, 키가 없으면 새 값을 삽입
1 |
|
개선된 ConcurrentHashMap
Java에서 멀티스레드 환경에서 안전하게 사용될 수 있는 해시맵 구현체로, 성능 최적화와 스레드 안전성을 동시에 제공하며, HashMap과 Hashtable의 단점을 보완한 컬렉션이다.
스레드 안전성
- 내부적으로 분할 잠금(Lock Striping) 기술을 사용하여 성능과 동시성을 개선
- 맵 전체가 아닌 특정 버킷(Bucket)에만 락을 걸기 때문에 다중 스레드에서도 효율적으로 동작
성능 최적화
- 락 경쟁 감소 : 데이터 구조를 여러 세그먼트(Segment)로 나누어 부분적인 락만 사용
- 비교적 낮은 락 비용 : Java 8부터는 세그먼트 기반 락을 제거하고 버킷에 대한 락만 사용
- 읽기 작업 대부분이 락 없이 수행 가능