backend-deep-dive / modern-java-in-action

모던 자바 인 액션 스터디
3 stars 6 forks source link

<Ch5 - 스트림 활용> #34

Closed hongxeob closed 1 year ago

hongxeob commented 1 year ago

범위

질문들을 통해 같은 주제를 다양한 관점에서 보고, 더욱 깊은 지식 습득을 목표로 합니다! 이곳에서 질문에 관한 내용을 구체적으로 토의해도 좋습니다!

SeungAh-Hong commented 1 year ago

3.6. 실전 연습 예제 5-5.

boolean milanBased = transactions.stream()
                .anyMatch(transaction -> transaction.getTrader().getCity().equals("Milan")); // anyMatch에 프레디케이트를 전달해서 밀라노에 거래자가 있는지 확인

여기서 equals가 anyMatch에 프레디케이트를 전달한다는 주석이 무슨 의미인지 모르겠어서 찾아보았습니다.

equals()가 반환하는 값이 Predicate인가? equals() 메소드는 Predicate 인터페이스를 직접 구현한 것이 아니기 때문에 반환값이 Predicate이라고 할 수는 없습니다. 그러나 equals() 메소드는 두 개의 인자를 받아 비교한 후 boolean 값을 반환합니다. 이 boolean 값을 람다 표현식에서 사용하여 Predicate를 구현할 수 있습니다.

그러면 여기서 쓰이는 Predicate를 전달한다는 뜻은 무엇인가? anyMatch는 다음과 같이 Predicate를 값으로 받습니다.

boolean java.util.stream.Stream.anyMatch(Predicate<? super Transaction> predicate)

예제 코드에서 사용되는 equals 메소드의 반환값인 boolean은 이미 기본형(primitive)으로 정의되어 있기 때문에, Java의 auto-boxing 기능으로 인해 바로 Predicate 타입으로 사용될 수 있습니다.

따라서, anyMatch 메소드에 전달되는 람다식에서 반환된 기본형 boolean 값은 auto-boxing되어 Predicate 타입으로 자동으로 변환되어 사용됩니다.

hongxeob commented 1 year ago

5.5 리듀싱 챕터의 마지막 부분쯤에 나오는 reduce와 병렬성에 대하여 조금 알아보다가 reduce의 초기값이 병렬 처리에 문제를 줄 수도 있다는 것을 알았습니다.

스트림은 병렬 처리를 위해 분할(divide) 및 병합(merge) 과정을 거칩니다. 초기값을 설정하지 않으면, 스트림을 분할할 때 초기값이 사용되지 않으므로 분할된 각 부분 스트림에서 reduce() 메서드가 실행될 때 다른 결과가 나올 수 있습니다. 예를 들어, 다음과 같은 코드를 고려해보겠습니다.

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.parallelStream().reduce(0, (a, b) -> a + b);

여기서 초기값으로 0을 설정하면, 분할된 각 부분 스트림에서도 0이 사용됩니다. 하지만, 초기값을 설정하지 않으면 각 부분 스트림에서는 서로 다른 초기값을 사용하게 됩니다. 그렇기 때문에 결과는 매번 다를 수 있습니다. 반대로 병렬 처리를 하지 않을 경우(그냥 sterem() 사용)에는 스트림이 순차적으로 처리 되므로 초기값을 설정하지 않아도 결과가 정확하게 나옵니다.

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream().reduce((a, b) -> a + b).orElse(0);

위 코드에서 reduce() 메서드에 초기값을 지정하지 않았으므로, 첫 번째 요소(1)가 초기값이 되어 reduce() 메서드가 호출됩니다. 그리고 reduce() 메서드는 두 번째 요소(2)부터 차례대로 호출되며, 모든 요소를 더한 값을 반환합니다. 따라서, 결과는 15가 됩니다. 즉, 순차 처리에서는 reduce() 메서드가 요소를 차례대로 처리하기 때문에, 초기값을 지정하지 않아도 첫 번째 요소가 초기값이 되어 정확한 결과를 얻을 수 있습니다. 결론 : 병렬 처리를 할 경우에는 초기값을 설정하는 것이 중요합니다.

vimkim commented 1 year ago

3.6. 실전 연습 예제 5-5.

예제 코드에서 사용되는 equals 메소드의 반환값인 boolean은 이미 기본형(primitive)으로 정의되어 있기 때문에, Java의 auto-boxing 기능으로 인해 바로 Predicate 타입으로 사용될 수 있습니다.

@SeungAh-Hong

boolean은 오직 Boolean으로 autoboxing 됩니다. Predicate<>으로 autoboxing될 수는 없습니다.

// anyMatch에 프레디케이트를 전달해서 밀라노에 거래자가 있는지 확인

위 주석은

transaction -> transaction.getTrader().getCity().equals("Milan")

이 람다식이 Predicate으로 자동 변환되어 anyMatch에 전달된다는 것을 뜻하는 것 같습니다.

모호한 부분을 확인해 주셔서 감사합니다!