귀찮지만 만들어보자

이펙티브 자바 - 람다와 스트림(5) 본문

이펙티브 자바

이펙티브 자바 - 람다와 스트림(5)

타우렌주술사 2019. 1. 19. 13:57


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


스트림 패러다임의 핵심은 계산을 일련의 변환으로 재구성 하는 부분이다.
이전 단계의 결과를 받아서 처리하는 과정에서(method chaining, fluent api) 원활하게 진행되려면,
스트림 연산에서 건내지는 함수 객체는 모두 부작용이 없어야 한다.
스트림 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);
  });
}
해당 예제에서 스트림, 람다, 메서드 참조를 사용했고, 결과도 올바르게 나온다.
하지만 스트림을 제대로 사용했다고 볼수 없다

Map<String, Long> freq = new HashMap();
try (List<String> words = new Scanner(file).tokens()) {
  for (String str: words) {
    freq.merge(str.toLowerCase(), 1L, Long::sum);
  }
}

이것과 비교했을 때 나은점이 하나도 없다.
스트림의 forEach가 모든 연산을 처리하는 것은 좋은 예시가 아니다.
forEach 연산은 스트림 계산 결과를 보고할 때만 사용하고, 계산하는데는 쓰지 말자
게다가 스트림의 forEach는 loop가 아니기 때문에 중간에서 연산을 중지할 수도 없다.

Map<String, Long> freq = new HashMap();
try (Stream<String> words = new Scanner(file).tokens()) {
  words.collect(groupingBy(String::toLowerCase, counting()));
}
스트림을 사용하려면 이런식으로 사용하도록 하자..