•원소 시퀀스, 일련의원소를 반환하는 메서드는 수없이 많지만 기본은 컬렉션 인터페이스이다.
•원소 시퀀스를 반환할때는 스트림을 사용한다는 이야기가 많지만
스트림은 반복을 지원하지 않음
•스트림과 반복을 알맞게 조합해야 좋은 코드가 나온다.
자바 타입 추론의 한계로 컴파일되지 않는 코드
for(ProcessHandle ph: ProcessHandel.allProcesses()::iterator{
//프로세스를 처리한다,
}
이오류를 해결하려면 메서드 참조를 매개변수화된 Iterable로 적절히 형변환 해야한다.
1)Stream< E >를 Iterable< E >로 중개해주는 어댑터
public static <E> Iterable<E> iterableOf(Stream<E> stream){
return stream::iterator;
}
어댑터를 사용하면 어떤 스트림도 for-each문으로 반복할수있다.
2)Iterable< E >를 Stream< E >로 중개해주는 어댑터
public static <E> Stream<E> streamOf(Iterable<E> iterable){
return StreamSupprot.stream(iterable.spliterator(),false);
}
>객체시퀀스를 반환하는 메서드를 작성할때!
•이 메서드가 오직 스트림파이프라인에서만 쓰일걸 안다면
마음놓고 스트림을 반환하게 해주자
•반대의 경우 반환된 객체들이 반복문에서만 쓰일걸 안다면 Iterable를 반환하자
•Collection 인터페이스는 Iterable의 하위타입이고 stream메서드도 제공하기때문에 반복과 스트림을 동시에 지원한다
=> 원소 시퀀스를 반환하는 공개 API의 반환타입에는 Collection이나 그 하위 타입을 쓰는게 일반적으로 최선이다.
Array의 경우 Array.asList와 Stream.of메서드로 손쉽게 반복과 스트림을 지원할수 있다.
반환하는 시퀀스의 크기가 메모리에 올릴정도로 안전하다면 괜찮지만
단지 컬렉션을 반환한다는 이유로 덩치 큰 시퀀스를 메모리에 올려서는 안된다
3) 반환할 시퀀스가 크지만 표현을 간결하게 할수있다면 전용 컬렉션을 구현하는 방안을 검토해보자
ex)멱집합을 반환하는 상황일때
AbStractList를 이용하면 전용 컬렉션을 손쉽게 구현 가능하다.
4)스트림을 반환하는 두가지 구현
AbstractCollection을 활용해서 구현체를 작성할 경우
Iterable용 메서드 외에 2개만 더 구현하면된다
contains와 size 메서드를 사용한다.
(1)입력리스트의 모든 부분리스트를 스트림으로 반환
import java.util.Collections;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class SubLists {
public static<E> Stream<List<E>> of(List<E> list){
return Stream.concat(Stream.of(Collections.emptyList()),prefixes(list).flatMap(SubLists::suffixes));
}
private static <E> Stream<List<E>> suffixes(List<E> list) {
return IntStream.range(0, list.size())
.mapToObj(start-> list.subList(start, list.size()));
}
private static <E> Stream<List<E>> prefixes(List<E> list){
return IntStream.rangeClosed(
1,list.size()).mapToObj(end -> list.subList(0,end));
}
}
concat메서드는 반환되는 스트림에 빈 리스트를 추가
flatMap메서드는 모든 프리픽스의 모든 서픽스로 구성된 하나의 스트림을 생성
프리피그와 서픽스들의 스트림은 IntStram.range와 rangeClosed가 반환하는 연속된 정숫값들을 매핑해서 만들었다.
for 반복문을 중첩해 만든것과 취지가 비슷함.
for(int start=0; start<src.size(); start++)
for(int end= start+1; end<=src.size(); end++)
System.out.println(src.subList(start,end));
이 반복문은 그대로 스트림으로 변환할수있다.
private static <E> Stream<List<E>> of(List<E> list){
return IntStream.range(0, list.size())
.mapToObj(start->IntStream.rangeClosed(start+1, list.size()).mapToObj(end->
list.subList(start,end))).flatMap(x->x);
}
1)원소시퀀스를 반환하는 메서드를 작성할경우 이를 스트림으로 처리하기를 원하는 사용자와 반복으로 처리하길 원하는 사용자가 모두 있음을 인지하고 양쪽을 모두 만족시키려 노력하자
2)컬렉션을 반환할수있다면 컬렉션을 반환
3)컬렉션을 반환하는게 불가능하다면 스트림과 Iterable중 더 자연스러운것을 반환