스트림을 사용한 BigDecimal 추가
Big Decimals 컬렉션이 있습니다(이 예에서는LinkedList
추가하겠습니다.이거 스트림으로 할 수 있어요?
나는 알아차렸다.Stream
클래스에는 몇 가지 메서드가 있습니다.
Stream::mapToInt
Stream::mapToDouble
Stream::mapToLong
각각 편리한 점이 있다.sum()
방법.하지만 알다시피float
그리고.double
산수는 거의 항상 나쁜 생각이다.
그렇다면, 빅 데코멘탈을 요약하는 편리한 방법이 있을까요?
이게 제가 지금까지 가지고 있는 암호입니다.
public static void main(String[] args) {
LinkedList<BigDecimal> values = new LinkedList<>();
values.add(BigDecimal.valueOf(.1));
values.add(BigDecimal.valueOf(1.1));
values.add(BigDecimal.valueOf(2.1));
values.add(BigDecimal.valueOf(.1));
// Classical Java approach
BigDecimal sum = BigDecimal.ZERO;
for(BigDecimal value : values) {
System.out.println(value);
sum = sum.add(value);
}
System.out.println("Sum = " + sum);
// Java 8 approach
values.forEach((value) -> System.out.println(value));
System.out.println("Sum = " + values.stream().mapToDouble(BigDecimal::doubleValue).sum());
System.out.println(values.stream().mapToDouble(BigDecimal::doubleValue).summaryStatistics().toString());
}
보다시피, 저는 빅데모럴을 요약하고 있습니다.BigDecimal::doubleValue()
(역시) 정확하지 않습니다.
후세를 위한 사후 응답 편집:
두 답변 모두 큰 도움이 되었습니다.조금 덧붙이고 싶은 것이 있습니다.실제 시나리오에서는 raw의 컬렉션은 포함되어 있지 않습니다.BigDecimal
s는 송장에 포장되어 있습니다.하지만, 나는 이것을 설명하기 위해 Aman Agnihotri의 답변을 수정할 수 있었습니다.map()
스트림의 함수:
public static void main(String[] args) {
LinkedList<Invoice> invoices = new LinkedList<>();
invoices.add(new Invoice("C1", "I-001", BigDecimal.valueOf(.1), BigDecimal.valueOf(10)));
invoices.add(new Invoice("C2", "I-002", BigDecimal.valueOf(.7), BigDecimal.valueOf(13)));
invoices.add(new Invoice("C3", "I-003", BigDecimal.valueOf(2.3), BigDecimal.valueOf(8)));
invoices.add(new Invoice("C4", "I-004", BigDecimal.valueOf(1.2), BigDecimal.valueOf(7)));
// Classical Java approach
BigDecimal sum = BigDecimal.ZERO;
for(Invoice invoice : invoices) {
BigDecimal total = invoice.unit_price.multiply(invoice.quantity);
System.out.println(total);
sum = sum.add(total);
}
System.out.println("Sum = " + sum);
// Java 8 approach
invoices.forEach((invoice) -> System.out.println(invoice.total()));
System.out.println("Sum = " + invoices.stream().map((x) -> x.total()).reduce((x, y) -> x.add(y)).get());
}
static class Invoice {
String company;
String invoice_number;
BigDecimal unit_price;
BigDecimal quantity;
public Invoice() {
unit_price = BigDecimal.ZERO;
quantity = BigDecimal.ZERO;
}
public Invoice(String company, String invoice_number, BigDecimal unit_price, BigDecimal quantity) {
this.company = company;
this.invoice_number = invoice_number;
this.unit_price = unit_price;
this.quantity = quantity;
}
public BigDecimal total() {
return unit_price.multiply(quantity);
}
public void setUnit_price(BigDecimal unit_price) {
this.unit_price = unit_price;
}
public void setQuantity(BigDecimal quantity) {
this.quantity = quantity;
}
public void setInvoice_number(String invoice_number) {
this.invoice_number = invoice_number;
}
public void setCompany(String company) {
this.company = company;
}
public BigDecimal getUnit_price() {
return unit_price;
}
public BigDecimal getQuantity() {
return quantity;
}
public String getInvoice_number() {
return invoice_number;
}
public String getCompany() {
return company;
}
}
원답
네, 가능합니다.
List<BigDecimal> bdList = new ArrayList<>();
//populate list
BigDecimal result = bdList.stream()
.reduce(BigDecimal.ZERO, BigDecimal::add);
기능:
- 를 입수하다
List<BigDecimal>
. - 로 변환합니다.
Stream<BigDecimal>
reduce 메서드를 호출합니다.
3.1. 델은 추가를 위해 ID 값을 제공합니다.즉,
BigDecimal.ZERO
.3.2. 다음 조건을 지정합니다.
BinaryOperator<BigDecimal>
2개의 추가가 있습니다.BigDecimal
의, 메서드 레퍼런스에 의한BigDecimal::add
.
편집 후 답변 업데이트
새로운 데이터를 추가했으므로 새로운 답변은 다음과 같습니다.
List<Invoice> invoiceList = new ArrayList<>();
//populate
Function<Invoice, BigDecimal> totalMapper = invoice -> invoice.getUnit_price().multiply(invoice.getQuantity());
BigDecimal result = invoiceList.stream()
.map(totalMapper)
.reduce(BigDecimal.ZERO, BigDecimal::add);
거의 똑같아. 다만, 내가 한 번 더했다.totalMapper
variable, from function이 있는 변수Invoice
로.BigDecimal
그리고 그 청구서의 총 가격을 반환합니다.
그 후, 저는Stream<Invoice>
, 에 매핑합니다.Stream<BigDecimal>
그리고 나서 그것을 a로 줄인다.BigDecimal
.
OOP 설계 관점에서, 저는 당신에게 실제로 사용하기를 권합니다.total()
이미 정의되어 있는 방법을 사용하면, 한층 더 간단하게 할 수 있습니다.
List<Invoice> invoiceList = new ArrayList<>();
//populate
BigDecimal result = invoiceList.stream()
.map(Invoice::total)
.reduce(BigDecimal.ZERO, BigDecimal::add);
여기서는 의 메서드레퍼런스를 직접 사용합니다.map
방법.
이 게시물에는 이미 체크된 답변이 있지만 답변이 null 값을 필터링하지 않습니다.정답은 Object:: non Null 함수를 술어로 사용하여 null 값을 방지해야 합니다.
BigDecimal result = invoiceList.stream()
.map(Invoice::total)
.filter(Objects::nonNull)
.filter(i -> (i.getUnit_price() != null) && (i.getQuantity != null))
.reduce(BigDecimal.ZERO, BigDecimal::add);
이것에 의해, null 값이 감소했을 때에 합계되는 것을 막을 수 있습니다.
의 값을 요약할 수 있습니다.BigDecimal
resuableCollector를 사용한 스트림 이름summingUp
:
BigDecimal sum = bigDecimalStream.collect(summingUp());
그Collector
다음과 같이 실장할 수 있습니다.
public static Collector<BigDecimal, ?, BigDecimal> summingUp() {
return Collectors.reducing(BigDecimal.ZERO, BigDecimal::add);
}
Big Decimal 목록을 집계하려면 다음 방법을 사용합니다.
List<BigDecimal> values = ... // List of BigDecimal objects
BigDecimal sum = values.stream().reduce((x, y) -> x.add(y)).get();
이 접근법에서는 각 BigDecimal을 BigDecimal로만 매핑하고 합계함으로써 이들을 줄입니다.이러한 어프로치에서는 다음 명령어를 사용하여 반환됩니다.get()
★★★★★★ 。
다음은 동일한 합계를 수행하는 또 다른 간단한 방법입니다.
List<BigDecimal> values = ... // List of BigDecimal objects
BigDecimal sum = values.stream().reduce(BigDecimal::add).get();
갱신하다
만약 편집된 질문에 수업과 람다 표현을 쓴다면 다음과 같이 쓸 것입니다.
import java.math.BigDecimal;
import java.util.LinkedList;
public class Demo
{
public static void main(String[] args)
{
LinkedList<Invoice> invoices = new LinkedList<>();
invoices.add(new Invoice("C1", "I-001", BigDecimal.valueOf(.1), BigDecimal.valueOf(10)));
invoices.add(new Invoice("C2", "I-002", BigDecimal.valueOf(.7), BigDecimal.valueOf(13)));
invoices.add(new Invoice("C3", "I-003", BigDecimal.valueOf(2.3), BigDecimal.valueOf(8)));
invoices.add(new Invoice("C4", "I-004", BigDecimal.valueOf(1.2), BigDecimal.valueOf(7)));
// Java 8 approach, using Method Reference for mapping purposes.
invoices.stream().map(Invoice::total).forEach(System.out::println);
System.out.println("Sum = " + invoices.stream().map(Invoice::total).reduce((x, y) -> x.add(y)).get());
}
// This is just my style of writing classes. Yours can differ.
static class Invoice
{
private String company;
private String number;
private BigDecimal unitPrice;
private BigDecimal quantity;
public Invoice()
{
unitPrice = quantity = BigDecimal.ZERO;
}
public Invoice(String company, String number, BigDecimal unitPrice, BigDecimal quantity)
{
setCompany(company);
setNumber(number);
setUnitPrice(unitPrice);
setQuantity(quantity);
}
public BigDecimal total()
{
return unitPrice.multiply(quantity);
}
public String getCompany()
{
return company;
}
public void setCompany(String company)
{
this.company = company;
}
public String getNumber()
{
return number;
}
public void setNumber(String number)
{
this.number = number;
}
public BigDecimal getUnitPrice()
{
return unitPrice;
}
public void setUnitPrice(BigDecimal unitPrice)
{
this.unitPrice = unitPrice;
}
public BigDecimal getQuantity()
{
return quantity;
}
public void setQuantity(BigDecimal quantity)
{
this.quantity = quantity;
}
}
}
서드파티의 의존관계에 개의치 않는 경우, Eclipse Collections에는 Collectors2라는 클래스가 있습니다.이 클래스에는 BigDecimal과 BigInteger의 합계를 위해 Collectors를 반환하는 메서드가 포함되어 있습니다.이러한 메서드는 함수(Function)를 파라미터로 사용하여 객체에서 BigDecimal 또는 BigInteger 값을 추출할 수 있습니다.
List<BigDecimal> list = mList(
BigDecimal.valueOf(0.1),
BigDecimal.valueOf(1.1),
BigDecimal.valueOf(2.1),
BigDecimal.valueOf(0.1));
BigDecimal sum =
list.stream().collect(Collectors2.summingBigDecimal(e -> e));
Assert.assertEquals(BigDecimal.valueOf(3.4), sum);
BigDecimalSummaryStatistics statistics =
list.stream().collect(Collectors2.summarizingBigDecimal(e -> e));
Assert.assertEquals(BigDecimal.valueOf(3.4), statistics.getSum());
Assert.assertEquals(BigDecimal.valueOf(0.1), statistics.getMin());
Assert.assertEquals(BigDecimal.valueOf(2.1), statistics.getMax());
Assert.assertEquals(BigDecimal.valueOf(0.85), statistics.getAverage());
주의: 저는 Eclipse Collections의 커밋입니다.
언급URL : https://stackoverflow.com/questions/22635945/adding-up-bigdecimals-using-streams
'programing' 카테고리의 다른 글
Vuex가 다른 어레이를 전달 (0) | 2022.08.30 |
---|---|
C의 비트 배열 정의 및 조작 방법 (0) | 2022.08.30 |
VueJS - 로컬 json 파일에서 vis.js 타임라인으로 데이터 읽기 (0) | 2022.08.30 |
C 프로그램을 여러 파일로 분할하려면 어떻게 해야 합니까? (0) | 2022.08.30 |
캐시 라인 크기를 프로그래밍 방식으로 가져오시겠습니까? (0) | 2022.08.30 |