공부 기록/Spring
[Spring WebFlux] CollectMap에 대하여
뵤옹
2023. 4. 10. 11:14
CollectMap이란?
- CollectMap은 Map 콜랙션으로 데이터를 모으는 리액터 모으기(aggregation) 연산 중 하나이다.
- 리액터 모으기의 종류에는 collectMap 이외에도 아래와 같은 종류가 있다.
1. List 형식으로 모으기 : collectList
2. Map의 값을 모으기 : collectMultiMap
3. 개수 새기 : count
4. 누적하기 : reduce
5. 누적하면서 값 생성하기 : scan
CollectMap의 형식
- Mono<Map<K, T>> collectMap(Function<? super T, ? extends K> keyExtractor)
- Mono<Map<K, V>> collectMap(Function<? super T, ? extends K> keyExtractor,
Function<? super T, ? extends V> valueExtractor) - Mono<Map<K, V>> collectMap(Function<? super T, ? extends K> keyExtractor,
Function<? super T, ? extends V> valueExtractor,
Supplier<Map<K, V>> mapSupplier)
collectMap의 형식에 따른 인자는 다음과 같다.
- key Extractor : 데이터에서 map의 key를 제공하는 함수
- value Extractor : 데이터에서 map의 value를 제공하는 함수
- mapSupplier : 사용할 map 객체를 제공(mapSupplier가 없는 메서드는 기본으로 HashMap을 사용)
// keyExtractor만 지정. 값은 그대로 사용.
Mono<Map<Integer, Tuple2<Integer, String>>> numTupMapMono =
Flux.just(Tuples.of(1, "일"), Tuples.of(2, "이"), Tuples.of(3, "삼"), Tuples.of(4, "사"))
.collectMap(x -> x.getT1()); // keyExtractor
// String을 리턴하는 valueExtractor 사용.
Mono<Map<Integer, String>> numLabelMapMono =
Flux.just(Tuples.of(1, "일"), Tuples.of(2, "이"), Tuples.of(3, "삼"), Tuples.of(4, "사"))
.collectMap(x -> x.getT1(), // keyExtractor
x -> x.getT2()); // valueExtractor
// Map으로 TreeMap 사용
Mono<Map<Integer, String>> numLabelTreeMapMono =
Flux.just(Tuples.of(1, "일"), Tuples.of(2, "이"), Tuples.of(3, "삼"), Tuples.of(4, "사"))
.collectMap(x -> x.getT1(), // keyExtractor
x -> x.getT2(), // valueExtractor
() -> new TreeMap<>()); // mapSupplier
특징
collectMap은 중복된 키가 존재하면 마지막 데이터와 관련된 값이 사용된다.
예를 들어 아래와 같이 Flux가 생성하는 데이터는 4개지만 키로 사용하는 값이 중복되면 실제 map에는 3과 4, 두 개의 데이터만 저장된다.
Flux.just(1, 2, 3, 4)
.collectMap(x -> x % 2)
.subscribe(map -> System.out.println(map)); // {0=4, 1=3}
예제
@Test
public void collectMap() {
Flux<String> animalFlux = Flux.just(
"aardvark", "elephant", "koala", "eagle", "kangaroo");
Mono<Map<Character, String>> animalMapMono =
animalFlux.collectMap(a -> a.charAt(0));
StepVerifier
.create(animalMapMono)
.expectNextMatches(map -> {
return
map.size() == 3 &&
map.get('a').equals("aardvark") &&
map.get('e').equals("eagle") &&
map.get('k').equals("kangaroo");
})
.verifyComplete();
Map의 key는 동물의 첫 번째 문자로 결정되고 value는 동물 이름 자체가 된다.( {'a':'aardvark'} )
elephant, eagle과 같이 첫 글자가 같은 경우는 나중에 나온 eagle이 value가 된다.
참조
https://javacan.tistory.com/entry/Reactor-Start-8-Aggregation
https://backtony.github.io/spring/2022-06-16-spring-webflux-1/
(후에 다른 다른 모으기 연산들이 추가될 수 있습니다.)