Effective Java Item 46

한주영·2024년 3월 14일
0

이펙티브자바

목록 보기
31/33

스트림에서는 부작용없는 함수를 사용하라

스트림 패러다임의 핵심

일련의 변환으로 재구성 하는 부분
이때 각 변환 단계는 가능한 한 이전 단계의 결과를 받아 처리하는 순수함수여야함.
-> 순수함수란?
오직 입력만이 결과에 영향을 주는 함수를 말함

스트림 패러다임을이해하지못한 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는 스트림이 수행한 계산결과를 보고해야할때만 이용해야한다.
스트림을 올바로 사용하려면 수집기를 잘 알아둬야한다

profile
백엔드개발자가 되고싶은 코린이:)

0개의 댓글