'How to Sum up all BigDecimal in list of Objects
was wondering if any of the lambda can achieve something like this with the class provided here
public class DataDto {
private BigDecimal baseAmt;
private BigDecimal revenueAmt;
private BigDecimal occupiedDays;
private String timeUnit;
}
List<DataDto> data = {from db}
Map<String, BigDecimal> map = dataDtos().stream()
.collect(Collectors.groupingBy(DataDto ::getTimePoint,
Collectors.reducing(BigDecimal.ZERO, DataDto ::getBaseAmt)));
How to grouping by getTimePoint and add all the big decimal to particular fields and return to the list.
Thanks for helping
Solution 1:[1]
I can do it with a for loop. But I have not yet been able to do it with streams.
Let’s simplify your problem by defining a record with only two member fields.
record Amount( LocalDate date , BigDecimal revenue ) { }
Make some example data. We have two BigDecimal values for each of two LocalDate keys. January 23rd has 7 and 42, while April 1 has 1.2 and 1.1.
List < Amount > amounts =
List.of(
new Amount( LocalDate.of( 2022 , Month.JANUARY , 23 ) , new BigDecimal( "7" ) ) ,
new Amount( LocalDate.of( 2022 , Month.APRIL , 1 ) , new BigDecimal( "1.2" ) ) ,
new Amount( LocalDate.of( 2022 , Month.APRIL , 1 ) , new BigDecimal( "1.1" ) ) ,
new Amount( LocalDate.of( 2022 , Month.JANUARY , 23 ) , new BigDecimal( "42" ) )
);
Loop those.
NavigableMap < LocalDate, BigDecimal > mapTotalByDate = new TreeMap <>();
for ( Amount amount : amounts )
{
if ( mapTotalByDate.get( amount.date() ) == null )
{
mapTotalByDate.put( amount.date , amount.revenue );
} else
{
mapTotalByDate.put( amount.date , mapTotalByDate.get( amount.date ).add( amount.revenue ) );
}
}
mapTotalByDate = {2022-01-23=49, 2022-04-01=2.3}
Or change that for loop to use switch rather than cascading if, as suggested by IntelliJ. I prefer this as it seems easier to read.
for ( Amount amount : amounts )
{
switch ( mapTotalByDate.get( amount.date() ) )
{
case null -> mapTotalByDate.put( amount.date , amount.revenue );
default -> mapTotalByDate.put( amount.date , mapTotalByDate.get( amount.date ).add( amount.revenue ) );
}
}
Eliminate one of lookup on the map.
for ( Amount amount : amounts )
{
BigDecimal subtotal = mapTotalByDate.get( amount.date() );
switch ( subtotal )
{
case null -> mapTotalByDate.put( amount.date , amount.revenue );
default -> mapTotalByDate.put( amount.date , subtotal.add( amount.revenue ) );
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
