Stream skip(long n) // 처음 n개의 요소 건너뛰기
Strema limit(long maxSize) // 스트림의 요소를 maxSize개로 제한
IntStream exampleStream = IntStream.rangeClosed(1, 10); // 1~10의 요소를 가진 스트림
exampleStream.skip(3).limit(5).forEach(System.out::print); // 45678
distinct()는 스트림에서 중복된 요소들 제거
filter()는 주어진 조건(Predicate)에 맞지 않는 요소를 걸러낸다.
// distinct()
IntStream exampleStream = IntStream.of(1,2,2,3,3,3,4,5,5,6);
exampleStream.distinct().forEach(System.out::print); // 123456
// filter()
IntStream example2Stream = IntStream.rangeClosed(1, 10);
example2Stream.filter(i -> i%2 ==0).forEach(System.out::print); // 246810
// filter()를 다른 조건으로 여러 번 사용. 두 문장의 결과는 같다.
example2Stream.filter(i -> i%2!=0 && i%3!=0).forEach(System.out::print); //157
example2Stream.filter(i -> i%2!=0).filter(i -> i%3!=0).forEach(System.out::print);
Stream sorted()
Stream sorted(Comparator<? super T> comparator)
Stream<String> strStream = Stream.of("dd","aaa","CC","cc","b");
strStream.sorted().forEach(System.out::print); // CCaaabccdd
// 기본정렬 역순
strStream.sorted(Comparator.reverseOrder());
// 대소문자 구분 없이
strStream.sorted(String.CASE_INSESITIVE_ORDER)
// 길이 순 정렬
strStream.sorted(Comparator.comparing(String::length))
//정렬 조건을 추가할 때는 thenComparing() 사용
studentStream.sorted(Comparator.comparing(Student::getBan)
.thenComparing(Student::getTotalScore)
.thenComparing(Student::getName)
.forEach(System.out::println);
스트림의 요소에 저장된 값 중에서 원하는 필드만 뽑아내거나, 특정 형태로 변환해야 할 때
map() 사용
// map()으로 Stream<File>을 Stream<String>으로 변환하기
Stream<File> fileStream = Stream.of(new File("Ex1.java"), new File("Ex2.java"));
Stream<String> filenameStream = fileStream.map(File::getName);
filenameStream.forEach(System.out::println);
// map() 여러 번 사용
fileStream.map(File::getName) // Stream<File> -> Stream<String>
.filter(s -> s.indexOf('.')!= -1) // 확장자 없는 것 제외
.map(s -> s.substring(s.indexOf('.')+1)) // Stream<String> -> Stream<String>
.map(String::toUpperCase) // 모두 대문자로 변환
.distinct()
.forEach(System.out::print);
연산과 연산 사이에 올바르게 처리되었는지 확인하려면 peek() 사용
forEach()와 달리 스트림의 요소를 소모하지 않으므로 연산 사이에 여러 번 사용 가능
fileStream.map(File::getName)
.filter(s -> s.indexOf('.') != -1) //확장자 없는 것 제외
.peek(s -> System.out.printf("filename=%s%n", s)) //파일명 출력
.map(s -> s.substring(s.indexOf('.')+1)) //확장자만 추출
.peek(s -> System.out.printf("extension=%s%n", s)) //확장자 출력
.forEach(System.out::println);
map()은 연산의 결과로 Stream 타입의 스트림을 반환하는데,
스트림의 요소를 숫자로 변환하는 경우 IntStream과 같은 기본형 스트림으로 변환하는 것이 더 유용할 수 있다.
DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper)
IntStream mapToInt(ToIntFunction<? super T> mapper)
LongStream mapToLong(ToLongFunction<? super T> mapper)
count()만 지원하는 Stream와 달리 IntStream과 같은 기본형 스트림은 숫자를 다루는데 편리한 메서드들을 제공한다.
int sum() //스트림의 모든 요소의 총합
OptionalDouble average() //sum() / (double)count()
OptionalInt max() //스트림의 요소 중 제일 큰 값
OptionalInt min() //스트림의 요소 중 제일 작은 값
이 메서드들은 최종연산이기 때문에 호출 후에 스트림이 닫힌다. 하나의 스트림에 sum()과 average()를 연속해서 호출할 수 없다.
IntStream scoreSteram = studentStream.mapToInt(Student::getTotalScore);
long totalScore = scoreStream.sum(); //sum()은 최종연산이라 호출 후 스트림이 닫힘
OptionalDouble average = scoreStream.average(); //에러. 스트림이 이미 닫혔다.
double d = average.getAsDouble(); //OptionalDouble에 저장된 값을 꺼내서 d에 저장
sum()과 average()를 모두 호출해야 할 때, 스트림을 또 생성해야 하므로 불편하다.
그래서 summaryStatistics()라는 메서드가 따로 제공된다.
IntSummaryStatistics stat = scoreStream.summaryStatistics();
long totalCount = stat.getCount();
long totalScore = stat.getSum();
double avgScore = stat.getAverage();
int minScore = stat.getMin();
int maxScore = stat.getMax();
스트림의 요소가 배열이거나 map()의 연산결과가 배열인 경우, 즉 스트림의 타입이 Stream<T[]>인 경우 Stream로 다루는 것이 더 편리할 때가 있다. 그럴 때는 map() 대신 flatMap()을 사용한다.
//요소가 문자열 배열(Stringp[])인 스트림이 있을 때,
Stream<String[]> strArrStrm = Stream.of(
new String[]{"abc", "def", "ghi"},
new String[]{"ABC", "GHI", "JKLMN"}
);
//각 요소의 문자열들을 합쳐 문자열이 요소인 스트림, 즉 Stream<String>으로 만들려고 할 때
//스트림의 요소를 변환하기 위해 map()을 쓴 뒤
//배열을 스트림으로 만들어주는 Arrays.stream(T[])를 사용한다.
Stream<Stream<String>> strStrStrm = strArrStrm.map(Arrays::stream);
//이럴 경우, Stream<String[]>을 map(Arrays::stream)으로 변환한 결과는
//Stream<String>이 아닌 Stream<Stream<String>>이다. 즉, 스트림의 스트림이다.
//각 요소의 문자열들이 합쳐지지 않고, 스트림의 스트림 형태가 되었다.
//이때 map()을 flatMap()으로 바꿔주면 Stream<String>의 결과를 얻을 수 있다.
Stream<Stream<String>> strStrStrm = strArrStrm.map(Arrays::stream);
Stream<String> strStrm = strArrStrm.flatMap(Arrays::stream);