람다와 스트림.

자바8에서 함수형 인터페이스, 람다, 메더스 참조 개념과 함께 스트림API가 추가됨. 이기능들을 효과적으로 사용하는 방법을 알아봄

아이템 42. 익명 클래스보다는 람다를 사용하라

// 익명 클래스
Collection.sort(words, new Comparator<String>() {
 public int compare(String s1, String s2) {
  return Integer.compare(s1.length(), s2.length());
 }
});

// 람다식
Collection.sort(words, (s1, s2) -> Integer.compare(s1.length(), s2.length()));

// 비교자 생성 메서드
Collection.sort(words, comparingInt(String::length));

// List 인터페이스에 추가된 sort
words.sort(comparingInt(String::length));

아이템 43. 람다보다는 메서드 참조를 사용하라

// 람다
map.merge(key, 1, (count, incr) -> count + incr);

// 메서드 참조
map.merge(key, 1, Integer::sum);

아이템 44. 표준 함수형 인터페이스를 사용하라

아이템 45. 스트림은 주의해서 사용하라

// 반복버전의 데카르트 곱
private static List<Card> newDeck() {
 List<Card> result = new ArrayList<>();
 for (Suit suit : Suit.values())
  for (Rank rank : Rank.values())
    result.add(new Card(suit, rank));
 return result;
}

// 스트림버전의 데카르트 곱
private static List<Card> newDeck() {
 return Stream.of(Suit.values())
   .flatMap(suit -> 
   Stream.of(Rank.values())
    .map(rank -> new Card(suit, rank)))
}

아이템 46. 스트림에서는 부작용 없는 함수를 사용하라

// 스트림 패러다임을 이해하지 못한채 사용된 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;
try (Stream<String> words = new Scanner(file).tokens()) {
 freq = words.collect(groupingBy(String::toLowerCase, counting()));
}

아이템 47. 반환 타입으로는 스트림보다 컬렉션이 낫다

아이템 48. 스트림 병렬화는 주의해서 적용하라