Collectors
: collect()가 스트림의 요소를 수집하는데에 대한 방법을 정의한다.
: static으로 제공하는 것을 가져다 사용할 수도 있고, Collector인터페이스를 구현받아서 직접 작성할 수도 있다.
💡Collector인터페이스
public interface Collector<T, A, R> {
Supplier<A> supplier();
BiConsumer<A,T> accumulator();
BinaryOperator<A> combiner();
Fuction<A, R> finisher();
Set<Characteristics> characteristics(); // 컬렉터의 특성이 담긴 Set을 반환
...
}
✔️ 직접 구현해야하는 것은 위의 5개의 메서드인데, Characteristics()를 제외하면 모두 반환타입이 함수형 인터페이스이다.
-> 4개의 람다식 작성이 필요하다.
함수 | 내용 |
supplier() | 작업결과를 저장할 공간을 제공 |
accumulator() | 스트림의 요소를 수집할 방법을 제공 |
combiner() | 병렬스트림의 경우, 여러 쓰레드에 의해 처리된 결과를 어떻게 합칠지에 대해 정의 |
finisher() | 결과를 반환할 방법을 제공, 변환이 필요없다면 항등함수인 Function.identity()를 반환. |
✔️ characteristics()는 컬렉터가 수행하는 작업의 속성에 대한 정보를 제공하기 위한것이다.
Characteristics.CONCURRENT | 병렬로 처리할 수 있는 작업 |
Characteristics.UNORDERED | 스트림의 요소가 순서가 유지될 필요가 없는 작업 |
Characteristics.IDENTITY_FINISH | finisher()가 항등 함수인 직업 |
/* 설정 예시 */
public Set<Characteristics> Characteristics(){
return Collections.unmodifiableSet(EnumSet.of(
Collector.Characteristics.CONCURRENT,
Collector.Characteristics.UNORDERED
));
}
/* 아무런 속성도 지정하고 싶지 않을 때, */
Set<Characteristics> Characteristics(){
return Collections.emptySet(); //비어있는 set반환
}
✔️ reduce()와 collect()
- finisher() 제외하고 supplier(), accumulator(), combiner()는 모두 리듀싱에도 있는 개념이다.
결국 Collector도 내부적으로 처리하는 과정이 리듀싱과 같다는 것을 의미한다.
- reduce()와 collect()는 근본적으로는 하는 일이 같다.
- collect()는 그룹화와 분할, 집계에 더 유용하게 쓰인다.
- 병렬화에 있어서는 reduce()보다 collect()가 더 유리하다.
✔️문자열을 하나로 결합하는 collector 구현예시
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class CollectorEx1 {
public static void main(String[] args) {
String[] strArr = {"aaa","bbb","ccc"};
Stream<String> strStream = Stream.of(strArr);
String result = strStream.collect(new ConcatCollector());
System.out.println(Arrays.toString(strArr));
System.out.println("result="+result);
}
}
class ConcatCollector implements Collector<String, StringBuilder,String>{
@Override
public Supplier<StringBuilder> supplier() {
/* 작업 결과를 저장할 공간을 제공 */
return ()->new StringBuilder();
// return StringBuilder::new;
}
@Override
public BiConsumer<StringBuilder, String> accumulator() {
/* 스트림의 요소를 수집할 방법 */
return (sb, s) -> sb.append(s);
// return StringBuilder::append;
}
@Override
public Function<StringBuilder, String> finisher() {
/* 결과 반환 방식 */
return sb-> sb.toString();
// return StringBuilder::toString;
}
@Override
public BinaryOperator<StringBuilder> combiner() {
/* 병렬 스트림의 경우 저장공간을 병합할 방법 */
return (sb, sb2) -> sb.append(sb2);
// return StringBuilder::append;
}
@Override
public Set<Characteristics> characteristics() {
/* 아무런 속성도 지정하지 않음 */
return Collections.emptySet();
}
}
출력결과는
[aaa, bbb, ccc]
result=aaabbbccc
이고, 주석을 풀고 람다식을 주석처리하여도 실행결과는 같다.
728x90
반응형
'개발 공부 > Java & Spring' 카테고리의 다른 글
26. 표준 입출력과 RandomAccessFile (0) | 2023.04.16 |
---|---|
25. 문자기반의 보조스트림 (0) | 2023.04.09 |
23. 스트림 - collect() (0) | 2023.03.26 |
22. 스트림의 최종연산 (0) | 2023.03.26 |
21. fork & join 프레임워크 (0) | 2023.03.09 |