티스토리 뷰
● 도입
- Stream 안의 데이터에 주어진 함수를 반복 적용해 데이터를 '하나의 값으로 합치는' 작업
(데이터가 하나만 남을 때까지 계속 적용)
- 최종적으로 남은 데이터를 return 한다.
- Max / Min / Count도 reduce의 일종이다.
- 위의 사진은 아래와 같은 방식으로 실행되는 것이다.
f(x, y)의 결과 = a → f(a, z)의 결과 = b → f(b, ...) * f 는 동일한 함수이다.
- 이러한 작업이 계속 반복되면서 결국에는 하나의 데이터만 남는 것이다.(해당 데이터가 return 된다.)
1.
Optional<T> reduce(BinaryOperator<T> accumulator);
- 주어진 accumulator를 Stream 안의 모든 데이터에 반복 적용을 해서 최종적으로 하나의 값을 도출한다.
- Stream이 비어있을 경우 빈 Optional을 반환
cf) BinaryOperator?
- BiFunction<T, U, R>에서 <T, U, R> 3개의 타입이 모두 같을때 대신하여 사용할 수 있다.
- input type과 output type이 모두 동일한 BiFunction이라고 생각하면 된다.
2.
T reduce(T identity, BinaryOperator<T> accumulator);
- 주어진 초기값과 accumulator를 이용, Stream 안의 모든 데이터에 반복 적용을 해서 최종적으로 하나의 값을 도출한다.
- 반복 작업에 대한 초기값을 제공한다. → T identity
- 주어진 초기값을 가지고 reduce 작업을 시작하는 것이다.
- 초기값이 있기 때문에 항상 반환값이 존재하며 그렇기에 반환 타입이 Optional<T> 이 아니라 T reduce 이다.
3.
<U> U reduce(U identity
, BiFunction<U, ? super T, U> accumulator
, BinaryOperator<U> combiner);
- U identity → U type의 초기값을 준다.
- BiFunction<U, ? super T, U> accumulator → Stream 안의 T type의 데이터와 계속 합쳐서 U type의 결과물을 만들어낸다.
- BinaryOperator<U> combiner → 병렬 작업시 필요
- reduce 작업에서 type이 바뀌는 경우에 사용(합치는 과정에서 타입이 바뀔 경우 사용)
- Map + reduce로 대체 가능하기에 해당 method는 많이 쓰이지는 않는다.
→ Map을 이용해 U type의 데이터로 바꾼 후
→ 그 후에 reduce 작업
● 실습
1.
package com.fastcampus.functionalprogramming.chapter8;
import java.util.Arrays;
import java.util.List;
import com.fastcampus.functionalprogramming.chapter8.model.User;
public class Chapter8Section4 {
public static void main(String[] args) {
// reduce를 이용해 Integer List의 합을 구해보자
List<Integer> numbers = Arrays.asList(1, 4, -2, -5, 3);
int sum = numbers.stream()
.reduce((x, y) -> x + y)
.get(); // Optional을 return 하기에 get()을 이용해 꺼낸다.
System.out.println("총합 : " + sum);
// min을 reduce를 이용해 구해보자
int min = numbers.stream()
.reduce((x, y) -> (x > y) ? y : x).get();
System.out.println("가장 적은 수 : " + min);
// ===================================================================================================
// 초기값을 제공
List<Integer> numbers2 = Arrays.asList(1, 4, -2, -5, 3);
int product = numbers2.stream()
.reduce(1, (x, y) -> x * y); // 초기값으로 1 을 제공, 초기값이 있기에 get()을 쓰지 않아도 된다.
System.out.println("곱 : " + product);
// ===================================================================================================
// String으로 담겨있는 숫자의 합을 구하자
List<String> numberStrList = Arrays.asList("3", "2", "5", "-4");
// map + reduce
int sumOfNumberStrList = numberStrList.stream()
.map(x -> Integer.parseInt(x))
.reduce(0, (x, y) -> x + y);
System.out.println("sumOfNumberStrList : " + sumOfNumberStrList);
// <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner); 이용
// U type은 Integer / T type은 String 이다.
// map + reduce 보다 복잡해 보이긴하다. 그래서 해당 method는 잘 사용하지는 않는다.
int sumOfNumberStrList2 = numberStrList.stream()
.reduce(0, (number, str) -> number + Integer.parseInt(str), (num1, num2) -> num1 + num2);
System.out.println("sumOfNumberStrList2 : " + sumOfNumberStrList2);
}
}
2. 각 user들의 친구 수 총합을 구해보자
package com.fastcampus.functionalprogramming.chapter8;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import com.fastcampus.functionalprogramming.chapter8.model.Order;
import com.fastcampus.functionalprogramming.chapter8.model.OrderLine;
import com.fastcampus.functionalprogramming.chapter8.model.User;
public class Chapter8Section4 {
public static void main(String[] args) {
User user1 = new User()
.setId(101)
.setName("Alice")
.setFriendUserIds(Arrays.asList(201, 202, 203, 204)); // 친구 4명
User user2 = new User()
.setId(102)
.setName("Bob")
.setFriendUserIds(Arrays.asList(204, 205, 206)); // 친구 3명
User user3 = new User()
.setId(103)
.setName("Charlie")
.setFriendUserIds(Arrays.asList(204, 205, 207)); // 친구 3명
List<User> users = Arrays.asList(user1, user2, user3);
// 각 user들의 친구 수 총합을 구해보자
int sumOfNumberOfFriends = users.stream()
.map(User::getFriendUserIds)
.map(List::size)
.reduce(0, (x, y) -> x + y);
System.out.println("친구 몇 명? " + sumOfNumberOfFriends);
}
}
3. 각 order의 OrderLine 들의 총합을 구해보자
package com.fastcampus.functionalprogramming.chapter8;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import com.fastcampus.functionalprogramming.chapter8.model.Order;
import com.fastcampus.functionalprogramming.chapter8.model.OrderLine;
import com.fastcampus.functionalprogramming.chapter8.model.User;
public class Chapter8Section4 {
public static void main(String[] args) {
// 숙제
Order order1 = new Order()
.setId(1001L)
.setOrderLines(Arrays.asList(
new OrderLine().setAmount(BigDecimal.valueOf(1000)),
new OrderLine().setAmount(BigDecimal.valueOf(2000))));
Order order2 = new Order()
.setId(1002L)
.setOrderLines(Arrays.asList(
new OrderLine().setAmount(BigDecimal.valueOf(2000)),
new OrderLine()
.setAmount(BigDecimal.valueOf(3000))));
Order order3 = new Order()
.setId(1002L)
.setOrderLines(Arrays.asList(
new OrderLine().setAmount(BigDecimal.valueOf(1000)),
new OrderLine().setAmount(BigDecimal.valueOf(2000))));
List<Order> orders = Arrays.asList(order1, order2, order3);
// 각 order의 OrderLine 들의 총합을 구해보자
BigDecimal sumOfAmounts = orders.stream()
.map(Order::getOrderLines) // Stream<List<OrderLine>>
.flatMap(List::stream) // Stream<OrderLine>
.map(OrderLine::getAmount) // Stream<BigDecimal>
.reduce(BigDecimal.ZERO, BigDecimal::add);
// .reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
System.out.println("sumOfAmounts : " + sumOfAmounts);
}
}
cf) java BigDecimal 연산
'Backend > Java8' 카테고리의 다른 글
#29 Advanced Stream - To Map (0) | 2022.10.18 |
---|---|
#28 Advanced Stream - Collectors (0) | 2022.10.17 |
#26 Advanced Stream - Find First / Find Any (1) | 2022.10.15 |
#25 Advanced Stream - All Match / Any Match (0) | 2022.10.14 |
#24 Advanced Stream - Max / Min / Count (0) | 2022.10.13 |
- Total
- Today
- Yesterday
- node.js
- 빅데이터 분석기사
- Advanced Stream
- 코테
- jpa
- API
- MySQL
- Phaser3
- Stream
- 메모리
- 운영체제
- SpringBoot
- 프로그래머스
- DART
- java
- OS
- nosql
- 프로세스
- SQL
- 빅데이터
- Spring Boot
- 자료구조
- git
- 알고리즘
- Phaser
- db
- spring
- MongoDB
- 코딩테스트
- Java8
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |