Search

Item 47. 반환 타입으로는 스트림보다 컬렉션이 낫다

생성일
2023/08/01 10:46
챕터
7장 - 람다와 스트림

요약

메서드에서 원소 시퀀스를 반환해야 한다면, 가급적 컬렉션을 반환하자.

스트림과 iteration

원소 시퀀스(일련의 원소들)를 반환하는 메서드에서 반환 타입은 Collection, Set, List와 같은 컬렉션 인터페이스와 Iterable, 배열이 사용되었다. 하지만 자바 8부터 스트림이 도입되고 나서 이러한 메서드들의 반환 타입에 스트림이라는 선택지가 생겼다.
스트림은 반복(iteration)을 지원하지 않기 때문에, 스트림과 반복을 알맞게 조합해야 좋은 코드를 만들 수 있다.
for (ProcessHandle ph : ProcessHandle.allProcesses()::iterator) { ... // 프로세스 처리 }
Java
복사
위 코드는 Stream의 iterator 메서드를 메서드 참조 방식으로 전달했지만, 지저분하고 가독성이 좋지않고 컴파일 오류가 발생한다.
public static <E> Iterable<E> iterableOf(Stream<E> stream) { return stream::iterator; } for (ProcessHandle ph : iterableOf(ProcessHandle.allProcesses())) { ... // 프로세스 처리 }
Java
복사
이와 같이 어댑터를 사용하면 모든 스트림을 for-each 문으로 반복할 수 있다.
public static <E> Stream<E> streamOf(Iterable<E> iterable) { return StreamSupport.stream(iterable.spliterator(), false); }
Java
복사
반대로 위처럼 iterator를 어댑터를 사용하여 스트림의 파이프라인으로 전달하기 할 수 있다.

원소 시퀀스 반환 타입

위의 두 어댑터를 통해 스트림 파이프라인에서만 사용된다면 스트림을 반환하고, 반복문에서만 사용된다면 Iterable을 반환하자.
Collection 인터페이스는 iterable의 하위 타입이고 stream 메서드를 제공하여 반복과 스트림을 동시에 지원한다.
공개 API에 적용하기에는 둘 다 지원을 해야하니, 원소 시퀀스를 반환하는 반환 타입에는 Collection이나 그 하위 타입을 사용하자.
하지만 컬렉션을 반환한다는 목적으로 큰 용량의 시퀀스를 메모리에 올리면 안된다. 반환할 시퀀스가 크지만 표현을 간결하게 할 수 있다면, 전용 컬렉션을 구현하여 해결하자.
전용 컬렉션을 구현할 때는 가급적 contains와 size를 구현하고, 이를 구현하는게 불가능하다면 컬렉션 보다 스트림이나 Iterable을 반환하는게 낫다.