Java

[Java] Collector 구현하기

Hyeonni 2022. 9. 18. 01:03

직접 Collector를 구현해서 스트림에 적용할 수 있다. 컬렉터를 직접 구현한다는 것은 Collector 인터페이스를 구현한다는 것을 의미한다.

 

Collector 인터페이스는 아래와 같이 정의되어 있다.

public interface Collector<T, A, R> {
	Supplier<A> supplier();
    BiConsumer<A, T> accumulator();
    BinaryOperator<A> combiner();
    Function<A, R> finisher();
    
    Set<Characteristics> characteristics(); //컬렉터의 특성이 담긴 Set을 반환
	
    '''

}

 

직접 구현해야 하는 것은 위의 5개 메서드이다. chracteristics()를 제외하면 모두 반환 타입이 함수형 인터페이스이므로 모두 람다식을 작성해 주어야 한다.

 

supplier()           작업 결과를 저장할 공간을 제공
accumulator()    스트림의 요소를 어떻게 수집(collect)할 방법을 제공
combiner()         두 저장공간을 병합할 방법을 제공(병렬 스트림)
finisher()            결과를 최종적으로 변환할 방법을 제공

 

  • supplier()는 수집 결과를 저장할 공간을 제공하기 위한 것이다.
  • accumulator()는 스트림의 요소를 어떻게 supplier()가 제공한 공간에 누적할 것인지를 정의한다.
  • combiner()는 병렬 스트림인 경우, 여러 쓰레드에 의해 처리된 결과를 어떻게 합칠 것인가를 정의한다.
  • finisher()는 작업결과를 변환하는 일을 하는데 변환이 필요 없다면, 항등 함수인 Function.identity()를 반환하면 된다.
  • characteristics()는 컬렉터가 수행하는 작업의 속성에 대한 정보를 제공하기 위한 것이다.
    • Characteristics.CONCURRENT : 병렬로 처리할 수 있는 작업
    • Characteristics.UNORDERED : 스트림의 요소의 순서가 유지될 필요가 없는 작업
    • Characteristics.IDENTITY_FINISH : finisher()가 항등 함수인 작업
public Set<Characteristics> characteristics() {
	return Collectoins.unmoidfiableSet(EnumSet.of(
    	Collector.Characteristics.CONCURRENT,
        Collector.Characteristics.UNORDERED));
}

public Set<Characteristics> characteristics() {
	return Collectoins.emptySet(); //지정할 특성이 없는 경우 비어있는 Set을 반환
}

 

 

reduce()와 collect()는 근본적으로 하는 일이 같다 하지만 collect()는 그룹화와 분할, 집계 등에 유용하게 쓰이고, 병렬화에 있어서 reduce()보다 collect()가 더 유리하다.

 

 

 

아래는 Stream<String>의 모든 문자열을 하나로 결합해서 String으로 반환하는 코드이다.