텍스트 파일에서 단어별 수를 세어 빈도표로 만드는 일
Map<String, Long> freq = new HashMap<>();
try(Stream<String> words = new Scanner(file).tokens())
words.forEach(word -> {
freq.merge(word.toLowerCase(), 1L, Long::sum);
});
}
스트림 코드를 가장한 반복적 코드
이 코드의 모든 작업이 종단 연산인 forEach에서 일어나는데, 이 때 외부 상태(빈도표)를 수정하는 람다를 실행하면서 문제가 생긴다
forEach는 그저 스트림이 수행한 연산 결과를 보여주는 일만 해야하는 데, 그 이상을 함
Map<String, Long> freq;
try (Stream<String> words = new Scanner(file).tokens()) {
freq = words.collect(groupingBy(String::toLowerCase, counting()));
}
// 빈도표에서 가장 흔한 단어 10개를 뽑아내는 스트림 파이프라인
List<String> topTen = freq.keySet().stream()
.sorted(comparing(freq::get).reversed())
.limit(10)
.collect(toList());
}
toMap(keyMapper, valueMapper)
// toMap 수집기를 사용하여 문자열을 열거 타입 상수에 매핑한다.
private static final Map<String, Operation> stringToEnum =
Stream.of(values()).collect(
toMap(Obejct::toString, e->e));
/*
다양한 음악가의 앨범들을 담은 스트림을 가지고,
음악가와 그 음악가의 베스트 앨범을 연관 짓고 싶은 예제
*/
Map<Artist, Album> topHits = albums.collect(
toMap(Album::artist, a->a, maxBy(comparing(Album::sales))));
// 마지막에 쓴 값을 취하는 수집기
toMap(keyMapper, valueMapper, (oldVal, newVal) -> newVal
// 알파벳화한 단어를 알파벳화 결가가 같은 단어들의 리스트로 매핑하는 맵 생성
words.collect(groupingBy(word -> alphabetsize(word)))