Skip to content

Latest commit

 

History

History
98 lines (70 loc) · 3.28 KB

반환타입은_스트림보다_컬렉션으로.md

File metadata and controls

98 lines (70 loc) · 3.28 KB

반환 타입은 스트림보다 컬렉션이 좋다.

엄청 당연한 이야기 같은데 페이지 분량이 많습니다.
대체 무슨 이야기를 하나 궁금해서 선택하게 되었습니다 ㅎㅎ

일련의 원소를 반환하는 메서드

  • 반환 타입으로 Collection, Set, List, Iterable, Array 등 다양
  • Java8에서 Stream 등장으로 복잡한 일 발생

Stream은 반복(iteration)을 지원하지 않는다.

item 45 참고

❗ stream만 반환하는 API

👉 API 사용자 🙍‍: 전 반환 값을 for-each로 반복하길 원했는데 안되네요?😡

여기서 의미하는 for-each는 stream().forEach()가 아닙니다!
for(String l : list) { ... }같은 형태를 의미합니다.

❓ Stream과 Iterable

Stream 인터페이스는 Iterable 인터페이스가 정의한 추상 메서드를 전부 포함하고 이들은 Iterable 인터페이스가 정의한 방식대로 동작한다.
그럼에도 for-each가 불가능한건 Stream이 Iterable을 extend 하지 않아서이다.

// Stream 인터페이스
public interface Stream<T> extends BaseStream<T, Stream<T>> {
    // ... 
}

public interface BaseStream<T, S extends BaseStream<T, S>>
        extends AutoCloseable {

    Iterator<T> iterator();
}

// Collection은 Iterable을 extend 한다.
public interface Collection<E> extends Iterable<E> {
    // ...
}

그렇다면 Stream과 Iterable을 같이 사용하는 방법을 생각해보겠다.

// ProcessHandle.allProcess()의 return 값: Stream<ProcessHandle>
// ProcessHandle: 기본 프로세스를 식별하고 제어하는 인터페이스
for(ProcessHandle processHandle : (Iterable<ProcessHandle>)ProcessHandle.allProcesses()::iterator){
    // 프로세스 처리
}

저 끔찍한 형변환이 보이는가?
안타깝게도 저 형변환이 없으면 method reference not expected here라는 컴파일 오류가 발생한다.

다행히 Stream를 Iterable로 중개해주는 메서드를 생성하면 조금 더 편안해진다.

public static <E> Iterable<E> iterableOf(Stream<E> stream) {
    return stream::iterator;
}

for(ProcessHandle processHandle : iterableOf(ProcessHandle.allProcesses())) {
    // 프로세스 처리
}

iterable만 반환하는 API

👉 API 사용자 🙍‍♂️‍: 전 반환 값을 스트림 파이프라인에서 처리하기를 원했는데 안되네요?😡

이러한 경우에도 Iterable을 Stream으로 중개해주는 메서드를 생성할 수 있다.

public static <E> Stream<E> streamOf(Iterable<E> iterable) {
    return StreamSupport.stream(iterable.spliterator(), false);
}

모두를 배려하는 API

API는 한 쪽만 지원하기 보다는 iterable, stream 모두를 배려해서 사용할 수 있게 만들자.
Collection이나 그 하위 타입으로 반환하도록 하자.

Collection을 사용하는 이유

  • Iterable의 하위 타입
  • stream 메서드 제공
  • 👉 반복과 스트림을 동시에 지원

덩치 큰 시퀀스

  • 컬렉션을 반환하기 위해 덩치 큰 시퀀스를 메모리에 올리는건 불필요한 일
  • 전용 컬렉션 구현도 고려해보자.

결론

👉 반환 타입으로는 Stream보다 Collection을 이용하자.