java stream을 통해 BigDecimal 합계 또는 연산하는 방법
부동소수점의 부정확성으로 인해 java에서는 소수점에 대한 정확한 계산이 요구되거나 화폐 단위를 사용할 때 BigDecimal 타입을 사용하는데요.
해당 포스팅은 'java에서 stream을 활용하여 BigDecimal을 연산하는 방법'에 대해 정리한 내용입니다.
코드 예시
List<BigDecimal> bigDecimalList = Arrays.asList(
BigDecimal.valueOf(1.123),
BigDecimal.valueOf(0.335),
BigDecimal.valueOf(2.10101),
BigDecimal.valueOf(0.54321)
);
//stream을 사용하지 않는 경우 연산
BigDecimal sum = BigDecimal.ZERO;
for (BigDecimal eachValue : bigDecimalList) {
sum = sum.add(eachValue);
}
다음과 같은 BigDecimal List가 있을 때 stream을 사용하지 않는다면 예시와 같이 for문 내부에서 add 메서드를 통해 연산을 수행할 수 있는데요.
//reduce 메서드 내부에서 람다식 사용
BigDecimal sum = bigDecimalList.stream().reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
//reduce 메서드 내부에서 사용되던 람다식을 메서드 참조 형식으로 사용
BigDecimal sum = bigDecimalList.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
Stream과 Stream의 reduce() 함수를 사용하게 되면 다음과 같이 코드를 조금 더 간결하게 사용할 수 있습니다.
***
reduce() 함수는 stream의 요소들을 하나의 데이터로 만드는 작업을 수행하는데요.
아래 3가지 파라미터를 받을 수 있으며, 위에서 사용된 함수는 identity와 accumulator를 인자로 받는 경우입니다.
T identity : 계산에 적용할 초기값으로 사용할 요소를 넣습니다. 스트림이 비어 있더라도 초기값을 반환합니다.
BinaryOperator<T> accumulator : BinaryOperator는 T 타입의 인자 두 개를 받고, T 타입의 객체를 리턴하는 함수형 인터페이스입니다.
BinaryOperator<U> combiner : 병렬 스트림에서 각 스레드의 결과를 합치데 사용되는 기능입니다.
T reduce(T identity, BinaryOperator<T> accumulator);
코드 예시 (객체 내부 BigDecimal의 경우)
@Setter
@Getter
@AllArgsConstructor
public class Invoice {
String invoiceNo;
BigDecimal unitPrice;
int quantity;
}
(예시에 사용할 Invoice Class)
List<Invoice> invoiceList = Arrays.asList(
new Invoice("a001", BigDecimal.valueOf(20.9), 2),
new Invoice("a002", BigDecimal.valueOf(5.15), 4),
new Invoice("a003", BigDecimal.valueOf(12.19), 3),
new Invoice("a004", BigDecimal.valueOf(3.999), 1)
);
//메서드 내부에서 람다식 사용
BigDecimal sum = invoiceList.stream().map(invoice -> invoice.getUnitPrice()).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
//람다식을 메서드 참조 형식으로 사용
BigDecimal sum = invoiceList.stream().map(Invoice::getUnitPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
예시와 같이 객체 내부의 BigDecimal을 연산할 때는 map() 메서드를 통해 BigDecimal 변수만 꺼내서 reduce() 메서드를 사용하면 되는데요.
//unitPrice x quantity 값을 더하고 싶은 경우
BigDecimal sum = invoiceList.stream().map(invoice -> invoice.getUnitPrice().multiply(BigDecimal.valueOf(invoice.getQuantity())))
.reduce(BigDecimal.ZERO, BigDecimal::add);
개당 가격(unitPrice) x 수량(qutntity) 값을 더하고 싶은 경우 다음과 같이 map으로 만들 때 계산을 하고 reduce()를 적용할 수도 있습니다.
< Java, BigDecimal을 사용해야 하는 이유 >
2022.08.18 - [Programming/Java] - Java - BigDecimal 사용하는 이유 (feat.부동소수점의 부정확성)
< 참고 자료 >
https://www.baeldung.com/java-stream-reduce
https://stackoverflow.com/questions/22635945/adding-up-bigdecimals-using-streams
'Programming > Java' 카테고리의 다른 글
java 임시 비밀번호 생성(SecureRandom 사용하는 이유) (0) | 2023.07.30 |
---|---|
Java Map 반복시키는 가장 효율적인 방법 (0) | 2023.07.26 |
java image resize library 이미지 리사이즈 라이브러리 비교해보기 (0) | 2023.07.15 |
Java 8, 11, 17 버전별 추가된 기능 (+ 무슨 버전을 써야할까?) (0) | 2023.07.05 |
java ip 접속 국가 정보 확인하기(GeoIP2, GeoLite2) (0) | 2023.06.29 |