일련의 변환으로 재구성 하는 부분
이때 각 변환 단계는 가능한 한 이전 단계의 결과를 받아 처리하는 순수함수여야함.
-> 순수함수란?
오직 입력만이 결과에 영향을 주는 함수를 말함
스트림 패러다임을이해하지못한 API만 사용한 코드
Map<String,Long> freq= new HashMap<>();
try(Stream<String> words= new Scanner(file).tokens()){
words.forEach(word->{
freq.merge(word.toLowerCase(), 1L, Long::sum);
});
}
스트림 API의 이점을 살리지 못해 같은 기능의 반복적 코드보다
길고 읽기어렵다, 유지보수에소도 좋지 않다.
스트림을 제대로 활용한 코드-> 빈도표를 초기화한다.
Map<String, Long> freq;
try(Stream<String> words= new Scanner(file).tokens()){
freq=
words.collect(groupingBy(String::toLowerCase,counting()));
}
forEach연산은 스트림 계산결과를 보고할때만 사용,계산할때는 쓰지말자
해당 코드는 수집기를 사용
수집기를 사용하면 스트림의 원소를 손쉽게 컬렉션으로 모을수있음.
수집기는 총 세가지이다
•toList()
•toSet()
•toCollection(collectionFactory)
1)빈도표에서 가장 흔한 단어 10개를뽑아내는 파이프라인
List<String> topTen= freq.keySet().stream()
.sorted(comparing(freq::get).reversed())
.limit(10)
.collect(Collectors.toList());
•comparing메서드는 키 추출 함수를 받는 비교자 생성메서드
•한정적 메서드 참조
•입력받은 단어를 빈도표에서 찾아 그 빈도를 반환
2)toMap수집기를 사용하여 문자열을 열거타입 상수에 매핑
private static final Map<String, Opreation> stringToEnum
=Stream.of(values()).collect(
toMap(Object::toString, e->e));
toMap형태는 스트림의 각 원소가 고유한 키에 매핑 되어 있을때 적합하다.
3) 각 키와 해당키의 특정 원소를 연관 짓는 맵을 생성하는 수집기
Map<Artist, Album> topHits= albums.collect(
toMap(Album::artist, a->a , maxBy (comparing(Album::sales))));
비교자로는 BinaryOperator에서 정적 임포트한 maxBy라는 정적 팩터리 메서드 사용
키 추출 함수로는 Album::sales를 받음.
인수가 3개인 toMap은 충돌이 나면 마지막 값을 취하는 수집기를 만들때도 유용하다.
4) 마지막에 쓴값을 취하는 수집기
toMap(keyMapper, valueMapper, (oldVal, newVal)-> newVal)
마지막toMap은 네번째 인수로 맵 팩터리를 받는다
이 인수로는 EnumMap이나 TreeMap처럼 원하는 특정 맵 구현체를 직접 지정가능하다.
4)Collector가 제공하는 groupingBy메서드
입력으로 분류함수를 받고 출력으로는 원소들을 카테코리 별로 모아놓은 맵을 담은 수집기를 반환
-> 분류함수는 입력받은 원소가 속하는 카테고리를 반환하는 역할
아이템45의 아나그램 프로그램에서 사용한 수집기로
알파벳화 한 단어를 알파벳화 결과가 같은 단어들의 리스트로 매핑하는 맵을 생성
words.collect(groupingBy(word-> alphabetize(word)))
스트림파이프라인의 프로그래밍의 핵심은 부작용없는 함수 객체에있다
스트림 관련 객체에 건네지는 모든 함수 객체가 부작용이 없어야한다.
종단 연산중 forEach는 스트림이 수행한 계산결과를 보고해야할때만 이용해야한다.
스트림을 올바로 사용하려면 수집기를 잘 알아둬야한다