-
스트림으로 데이터 수집Java/모던자바인액션요약 2022. 8. 23. 00:01728x90
개요
만약 통화별로 트랜잭션을 그룹화하기 위해서 코드를 작성하려면 어떻게 해야 할까요?
Map<Currency, List<Transaction>> transactionByCurrencies = new HashMap<>(); //트렌젝션 리스트에서 하나씩 꺼내옴 for(Transaction transaction : transactions){ Currency currency = transaction.getCurretncy(); List<Transaction> transactionForCurrency = transactionByCurrencies.get(currency); if(transactionForCurrency == null){ transactionForCurrency = new ArrayList<>(); transactionByCurrencies.put(currency, transactionForCurrency); } transactionForCurrency.add(transaction); }
'통화별로 트랜잭션 리스트를 그룹화하시오' 라고 간단히 표현할 수 있지만 코드가 무엇을 실행하는지 한눈에 파악하기 힘듭니다.
Stream에 toList를 사용하는 대신 더 범용적인 컬렉션 파라미터를 collect 메서드에 전달함으로써 원하는 연산을 훨씬 간결하게 구할 수 있습니다.
Map<Currency, List<Transaction>> transactionByCurrencies = transactions.stream().collect(groupingBy(Transaction::getCurrency));
훨씬 간단해진 모습을 볼 수 있습니다.
컬렉터란 무엇인가?
이전 예제에서 collect 메서드로 Collector 인터페이스 구현체를 전달했습니다.
'각 요소를 리스트로 만들어라'를 의미하는 toList를 사용했습니다.
컬렉터는 리듀싱 연산을 이용해서 스트림의 각 요소를 방문하며 컬렉터가 작업을 처리합니다.
위의 예시인 groupingBy 같은 컬렉터 인터페이스 구현체를 사용하면 각 트렌젝션에서 통화를 추출한 다음에 통화를 키로 사용해서 트랜젝션 자체를 결과 맵에 누적시킵니다.
보통 구현되어 있는 컬렉터들은 크게 세 가지로 구분할 수 있습니다.
- 스트림 요소를 하나의 값으로 리듀스 하고 요약
- 요소 그룹화
- 요소 분할
제공되는 컬렉터들 기능 요약
counting()
개수를 측정
maxBy(), minBy()
인자로 Comparator가 들어가며 최대/최소 값을 계산할 수 있습니다.
summingInt()
인자로 객체를 int로 매핑하는 함수를 받아 값의 합을 계산할 수 있습니다.
유사한 메서드로 summingDouble, summingLong이 있습니다.
이외에도 averagingInt, averagingDouble, averagingLong, summarzingInt 등의 메서드들이 있습니다.
joining()
인자를 넣어서 두 요소 사이에 구분 문자열을 넣을 수도 있습니다.
내부적으로 StringBuilder를 이용해서 문자열을 하나로 만들어줍니다.
reducing()
위의 모든 켈렉터들은 reducing 팩토리 메서드로 구현할 수 있습니다.
그럼에도 위의 컬렉터들을 소개한 이유는 프로그래밍적으로 편의성, 가독성이 증가하기 때문입니다.
groupingBy()
인자로 분류함수를 넣어주어야 합니다.
쉽게 그룹핑 할 수 있습니다.
각 키에 대응하는 스트림의 모든 항목을 리스트를 값으로 갖는 맵이 반환됩니다.
partitioningBy()
인자로 Boolean을 반환하는 분할 함수를 넣어주어야 합니다.
쉽게 분할할 수 있습니다.
최대 두 개의 그룹으로 분류됩니다(참 or 거짓)
Collector 인터페이스 직접 구현하기
public interface Collector<T, A, R>{ Supplier<A> supplier(); BiConsumer<A, T> accumulator(); Function<A, R> finisher(); BinaryOperator<A> combiner(); Set<Characteristics> characteristics(); }
다섯 가지 메서드를 직접 구현하여 자신만의 커스텀 컬렉터를 만들 수 있습니다.
직접 커스텀한 컬렉터를 구현할 수 있으며 이를 통해 성능 향상도 노려볼 수 있습니다.
개인적으로 아직 잘 와닿지 않는 부분이라 디테일하게 읽고 정리하진 않았습니다.
'Java > 모던자바인액션요약' 카테고리의 다른 글
컬렉션 API 개선 (0) 2022.09.06 병렬 데이터 처리와 성능 (0) 2022.08.29 스트림 활용 (0) 2022.08.18 스트림 소개 (0) 2022.08.15 람다 표현식 (0) 2022.08.10