Using Java 8 + JavaFX
I am trying to do some data analysis and output my results to an XY Chart. I've gotten my chart itself squared away, and it accepts a structure like:
ObservableList<Data<Timestamp, BigDecimal>>
My data is stored in a custom object, like so
public class funds{
private long id;
private String userName;
private BigDecimal current;
private Timestamp createdAt;
....constructors/getters/setters....
}
a funds object gets created for every user, by a recurring Task on a 1 minute interval.
I'd like to chart an hourly average sum of all funds.current.
So I'd normally sum up each minute for all users, and then avg that for each hour. In MySQL I can do this:
SELECT FLOOR(UNIX_TIMESTAMP(created_at)/(60*60)) AS hour, AVG(current)
FROM (
SELECT FLOOR(UNIX_TIMESTAMP(created_at)/60) AS minute, SUM(current) as current, created_at
FROM funds
GROUP BY minute
) as table1
GROUP BY hour;
But in this instance, I don't have direct SQL access, and must use java. I have tried looking at streams and the Collectors.groupingBy, but I cannot wrap my head around it enough to get what I want.
Also the Collectors seem to not have any functions for use with BigDecimal, which I need, as doubles are completely terrible for financial data.
Can anyone point me in the right direction?
If you really don't want to use doubles, try this:
Map<Long, BigDecimal> hourAverages = funds.stream()
//group by minute; as a result we have Map<Long, BigDecimal>
.collect(toMap(f -> f.createdAt.getTime() / 6000, f -> f.current, BigDecimal::add))
.entrySet().stream()
//group by hours; here we use BigDecimal[] to store sum and count;
//as a result we have Map<Long, BigDecimal[]>
.collect(groupingBy(e -> e.getKey() / 60,
collectingAndThen(
reducing(new BigDecimal[] {BigDecimal.ZERO, BigDecimal.ZERO},
e -> new BigDecimal[]{e.getValue(), BigDecimal.ONE},
(a, b) -> new BigDecimal[]{a[0].add(b[0]), a[1].add(b[1])}),
//finally divide by count
a -> a[0].divide(a[1], BigDecimal.ROUND_UP))));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With