map
, filter
, sorted
등의 중간 연산이 있다.collect
foreach
reduce
등이 있다.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
를 사용해 외부 상태인 freq
맵을 수정한다foreach
는 스트림 계산 결과를 보고할 때만 사용하고, 계산하는 데는 쓰지 말아야 한다.Map<String, Long> freq;
try (Stream<String> words = new Scanner(file).tokens()) {
freq = words.collect(Collectors.groupingBy(String::toLowerCase, Collectors.counting()));
}
collect
메서드를 사용하여 스트림의 원소를 그룹화, 각 그룹의 원소 개수를 세는 수집기를 사용함.List<String> topTen = freq.keySet().stream()
.sorted(Comparator.comparing(freq::get).reversed())
.limit(10)
.collect(Collectors.toList());
toMap
수집기 사용toMap
은 원소들을 맵으로 수집시 사용.키에 매핑하는 함수
값에 매핑하는 함수를 인수로 받는다.
toMap
수집기기본 형태의 toMap
수집기는 각 스트림 원소가 고유한 키를 가질 때 적합함.
만약 키가 중복되는 경우, IllegalStateException
이 발생할 수 있음.
private static final Map<String, Operation> stringToEnum =
Stream.of(values()).collect(toMap(Object::toString, e -> e));
toMap
수집기키 중복 문제를 해결하기 위해 세 번째 인수로 병합 함수 제공가능
- 키에 대해 값을 병합하는 역할을 한다
Map<Artist, Album> topHits = albums.collect(
toMap(Album::artist, a -> a, maxBy(comparing(Album::sales)))
);
각 음악가의 앨범들 중 가장 많이 판매된 앨범을 선택하는 병합 함수이다.
toMap
수집기toMap(keyMapper, valueMapper, (oldVal, newVal) -> newVal)
키가 중복되는 경우 마지막 값(새로운 값) 을 선택한다.
toMap
수집기4 번째 인수로 맵 팩토리를 제공하여 특정 맵 구현체를 사용한다.
예를 들어
- TreeMap
사용하고 싶자면 다음과 같이 작성한다
```java
toMap(keyMapper, valueMapper, mergeFunction, TreeMap::new)
```
groupingBy
수집기스트림의 원소들을 카테고리별로 그룹화해 맵으로 수집한다.
public class Main {
public static void main(String[] args) {
// 단어 목록을 리스트로 생성
List<String> wordList = Arrays.asList("listen", "silent", "enlist", "google", "gogole", "evil", "vile", "live");
// 리스트를 스트림으로 변환
Stream<String> words = wordList.stream();
Map<String, List<String>> anagrams = words.collect(
groupingBy(Main::alphabetize)
);
anagrams.forEach((k, v) -> {
System.out.println(k + ": " + v);
});
}
private static String alphabetize(String s) {
char[] a = s.toCharArray();
Arrays.sort(a);
return Arrays.toString(a);
}
}
words.collect
에서
alphabetize
를 수행한다.[e, i, l, n, s, t]
문자열로 반환groupingBy
public class Main {
public static void main(String[] args) {
// 단어 목록을 리스트로 생성
List<String> wordList = Arrays.asList("apple", "BANANA", "apple", "banana", "apple", "banana", "apple", "banana", "apple", "banana");
// 리스트를 스트림으로 변환
Stream<String> words = wordList.stream();
Map<String, Long> anagrams = words.collect(
groupingBy(String::toLowerCase, counting())
);
anagrams.forEach((k, v) -> {
System.out.println(k + ": " + v);
});
}
}
banana: 5
apple: 5
groupingBy
Map<String, Long> anagrams = words.collect(
groupingBy(String::toLowerCase, TreeMap::new, counting())
);
TreeMap
으로 그룹화하고, 각 그룹의 값을 Set
으로 수집한다.foreach
는 스트림이 수행한 계산 결과를 보고할 때만 사용해야한다.