티스토리 뷰
● 도입
- java의 함수들도 서로 합성할 수 있다.
- 위 그림은 f(x) 함수를 먼저 실행한 후 g(x) 함수를 실행하는 것이다.
java.util.function.Function
<V> Function<V, R> compose(Function<? super V, ? extends T> before)
<V> Function<T, V> andThen(Function<? super R, ? extends V> after)
compose
- parameter로 들어온 함수를 먼저 실행한 후 자기 자신을 실행하도록 합성
- 위 사진이 compose의 예이다.
andThen
- 자신을 먼저 실행한 후 parameter로 들어온 함수를 실행하도록 합성
● 실습
1. 두 함수를 합성해보자
package com.fastcampus.functionalprogramming.chapter9;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import com.fastcampus.functionalprogramming.chapter9.model.Order;
import com.fastcampus.functionalprogramming.chapter9.model.OrderLine;
import com.fastcampus.functionalprogramming.chapter9.priceprocessor.OrderLineAggregationPriceProcessor;
import com.fastcampus.functionalprogramming.chapter9.priceprocessor.TaxPriceProcessor;
public class Chapter9Section3 {
public static void main(String[] args) {
// 아래의 두 함수를 (x * 2 + 10)으로 합성해보자
Function<Integer, Integer> multiplyByTwo = x -> x * 2;
Function<Integer, Integer> addTen = x -> x + 10;
Function<Integer, Integer> composedFunction = multiplyByTwo.andThen(addTen);
System.out.println(composedFunction.apply(3));
/*
* 순서
* (1). multiplyByTwo : 3 * 2
* (2). addTen : 6 + 10
*/
}
}
2. 각자의 기능을 갖고 있는 함수들을 합성해서 새로운 함수를 만들어보자
- Order를 받아 해당 Order의 가격을 process 해주는 함수를 만들어보자
package com.fastcampus.functionalprogramming.chapter9.model;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
public class Order {
private long id;
private LocalDateTime createdAt;
private long createdByUserId;
private OrderStatus status;
private BigDecimal amount;
private List<OrderLine> orderLines;
public enum OrderStatus {
CREATED,
IN_PROGRESS,
ERROR,
PROCESSED
}
public long getId() {
return id;
}
public Order setId(long id) {
this.id = id;
return this;
}
public LocalDateTime getCreatedAt() {
return createdAt;
}
public Order setCreatedAt(LocalDateTime createdAt) {
this.createdAt = createdAt;
return this;
}
public long getCreatedByUserId() {
return createdByUserId;
}
public Order setCreatedByUserId(long createdByUserId) {
this.createdByUserId = createdByUserId;
return this;
}
public OrderStatus getStatus() {
return status;
}
public Order setStatus(OrderStatus status) {
this.status = status;
return this;
}
public BigDecimal getAmount() {
return amount;
}
public Order setAmount(BigDecimal amount) {
this.amount = amount;
return this;
}
public List<OrderLine> getOrderLines() {
return orderLines;
}
public Order setOrderLines(List<OrderLine> orderLines) {
this.orderLines = orderLines;
return this;
}
}
package com.fastcampus.functionalprogramming.chapter9.model;
import java.math.BigDecimal;
public class OrderLine {
private long id;
private OrderLineType type;
private long productId;
private int quantity;
private BigDecimal amount;
public enum OrderLineType {
PURCHASE,
DISCOUNT
}
public long getId() {
return id;
}
public OrderLine setId(long id) {
this.id = id;
return this;
}
public OrderLineType getType() {
return type;
}
public OrderLine setType(OrderLineType type) {
this.type = type;
return this;
}
public long getProductId() {
return productId;
}
public OrderLine setProductId(long productId) {
this.productId = productId;
return this;
}
public int getQuantity() {
return quantity;
}
public OrderLine setQuantity(int quantity) {
this.quantity = quantity;
return this;
}
public BigDecimal getAmount() {
return amount;
}
public OrderLine setAmount(BigDecimal amount) {
this.amount = amount;
return this;
}
}
package com.fastcampus.functionalprogramming.chapter9.priceprocessor;
import java.math.BigDecimal;
import java.util.function.Function;
import com.fastcampus.functionalprogramming.chapter9.model.Order;
import com.fastcampus.functionalprogramming.chapter9.model.OrderLine;
// 전체 가격을 합한 후 해당 가격을 order에 set 해주는 Processor
public class OrderLineAggregationPriceProcessor implements Function<Order, Order> {
@Override
public Order apply(Order order) {
return order.setAmount(order.getOrderLines().stream()
.map(OrderLine::getAmount)
.reduce(BigDecimal.ZERO, BigDecimal::add));
}
}
package com.fastcampus.functionalprogramming.chapter9.priceprocessor;
import java.math.BigDecimal;
import java.util.function.Function;
import com.fastcampus.functionalprogramming.chapter9.model.Order;
// 현재 가격에 세율을 적용하는 Processor
public class TaxPriceProcessor implements Function<Order, Order>{
private final BigDecimal taxRate;
public TaxPriceProcessor(BigDecimal taxRate) {
this.taxRate = taxRate;
}
@Override
public Order apply(Order order) {
return order.setAmount(order.getAmount()
.multiply(taxRate.divide(new BigDecimal(100)).add(BigDecimal.ONE)));
// cf)
// 세금 계산식은 굳이 이해를 하지 말자, 어차피 이게 메인도 아니다.
// 무엇보다 사실 봐도 잘 모르겠다.
}
}
package com.fastcampus.functionalprogramming.chapter9;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import com.fastcampus.functionalprogramming.chapter9.model.Order;
import com.fastcampus.functionalprogramming.chapter9.model.OrderLine;
import com.fastcampus.functionalprogramming.chapter9.priceprocessor.OrderLineAggregationPriceProcessor;
import com.fastcampus.functionalprogramming.chapter9.priceprocessor.TaxPriceProcessor;
public class Chapter9Section3 {
public static void main(String[] args) {
// 각자의 기능을 갖고 있는 함수들을 합성해서 새로운 함수를 만들어보자
// 목표 : order를 받아 해당 order의 가격을 process 해주는 함수를 만들어보자
/*
* 현재 가격을 process 해주는 함수가 2개 존재하는 상황이다.
* 1. OrderLine의 가격 총합을 Order에 set 해주는 함수
* 2. Tax Rate를 적용해 Order 가격에 반영하는 함수
*/
Order unprocessedOrder = new Order()
.setId(1001L)
.setOrderLines(Arrays.asList(
new OrderLine().setAmount(BigDecimal.valueOf(1000)), // 1000원 짜리 주문
new OrderLine().setAmount(BigDecimal.valueOf(2000)))); // 2000원 짜리 주문
// 두 개의 PriceProcessor를 return 받았다.
List<Function<Order, Order>> priceProcessors = getPriceProcessors();
// getPriceProcessors method를 통해 받은 PriceProcessor 들을 하나로 합쳐서 '합성된 PriceProcessor'로 만들자
Function<Order, Order> mergedPriceProcessors = priceProcessors.stream()
.reduce(Function.identity(), Function::andThen); // Function::andThen을 이용해 코드를 더 간단하게
// .reduce(Function.identity(), (priceProcessor1, priceProcessor2) -> priceProcessor1.andThen(priceProcessor2));
/*
* Function.identity()를 이용해 reduce 작업의 초기값 제공
* 초기값 = Order를 받아 그대로 Order를 return 하는 Function<Order, Order> (다른 작업은 없다.)
*/
Order processedOrder = mergedPriceProcessors.apply(unprocessedOrder);
System.out.println(processedOrder.getAmount());
}
// 두 개의 PriceProcessor를 return 하는 함수
public static List<Function<Order, Order>> getPriceProcessors() {
return Arrays.asList(
new OrderLineAggregationPriceProcessor(),
new TaxPriceProcessor(new BigDecimal("9.375"))); // "9.375" = 적용할 세율
}
}
'Backend > Java8' 카테고리의 다른 글
#37 Design Pattern - Builder Pattern (0) | 2022.10.26 |
---|---|
#36 Design Pattern (0) | 2022.10.25 |
#35 함수형 프로그래밍 응용 - Lazy Evaluation(for 최적화) (0) | 2022.10.24 |
#34 함수형 프로그래밍 응용 - Scope & Closure / Curry (0) | 2022.10.23 |
#33 Advanced Stream - Parallel Stream(병렬 Stream) (0) | 2022.10.22 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- Advanced Stream
- Stream
- 빅데이터 분석기사
- node.js
- Java8
- Spring Boot
- jpa
- spring
- java
- 빅데이터
- 자료구조
- OS
- MongoDB
- 코테
- API
- nosql
- git
- 운영체제
- 메모리
- Phaser
- 프로세스
- MySQL
- db
- Phaser3
- 알고리즘
- SpringBoot
- 코딩테스트
- DART
- 프로그래머스
- SQL
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
글 보관함