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

문법식·2022년 10월 4일
0

Effective Java 3/E

목록 보기
47/52

원소 시퀀스, 즉 일련의 원소를 반환하는 방법은 여러 가지다. 기본은 컬렉션 인터페이스다. for-each문에서만 쓰어기나 반환된 원소 시퀀스가 일부 Collection 메서드를 구현할 수 없을 때는 Iterable 인터페이스를 썼다. 반환 원소들이 기본 타입이거나 성능에 민감한 상황이라면 배열을 썼다. 그런데 자바 8에서 스트림이라는 개념이 들어오면서 복잡해졌다.

스트림은 반복을 지원하지 않는다. 따라서 스트림과 반복을 알맞게 조합해야 좋은 코드가 나온다. 사실 Stream 인터페이스는 Iterable 인터페이스가 정의한 추상 메서드를 전부 포함할 뿐만 아니라, Iterable 인터페이스가 정의한 방식대로 동작한다. 그럼에도 for-each로 스트림을 반복할 수 없는 이유는 StreamIterable을 확장하지 않아서다. 이 문제를 해결할 깔끔한 우회로가 존재하지 않는다. 자바 타입 추론의 한계로 코드가 지저분해진다. 그나마 어댑터 메서드를 사용하면 상황이 나아진다.

공개 API를 작성할 때는 스트림 파이프라인을 사용하는 사람과 반복문에서 쓰려는 사람 모두를 배려해야 한다. 사용자 대부분이 한 방식만 사용할거라는 근거가 없다. Collection 인터페이스는 Iterable의 하위 타입이고 stream 메서드도 제공하니 반복과 스트림을 동시에 지원한다. 따라서 원소 시퀀스를 반환하는 공개 API의 반환 타입에는 Collection이나 그 하위 타입을 쓰는 게 일반적으로 최선이다. 반환하는 시퀀스의 크기가 메모리에 올려도 안전할 만큼 작다면 ArrayListHashSet 같은 표준 컬렉션 구현체를 반환하는 것도 좋다. 하지만 단지 컬렉션을 반환한다는 이유로 덩치 큰 시퀀스를 메모리에 올려서는 안 된다.
반환할 시퀀스가 크지만 표현을 간결하게 할 수 있다면 전용 컬렉션을 구현하는 방안도 검토해보면 좋다. AbstractCollection을 활용해서 Collection 전용 구현체를 작성할 때는 Iterable 용 메서드 외에 containsize 메서드만 더 구현하면 된다. 만약 containsize를 구현하는 게 불가능할 때는 컬렉션보다는 스트림이나 Iterable을 반환하는 편이 낫다.

핵심은 원소 시퀀스를 반환하는 메서드를 작성할 때는, 이를 스트림으로 처리하기를 원하는 사요앚와 반복으로 처리하길 원하는 사용자가 모두 있을 수 있음을 떠올리고, 양쪽을 모두 만족시키려 노력해야 한다는 것이다. 컬렉션을 반환할 수 있으면 반환하고, 그렇지 않으면 전용 컬렉션을 구현할지 고민해봐야 한다. 컬렉션으로 반환하는 게 불가능하면 스트림과 Iterable 중 더 자연스러운 것을 반환해야 한다.

profile
백엔드

0개의 댓글