使用Java 8 + JavaFX
我正在尝试进行一些数据分析,并将结果输出到XY图表。
我已经弄清楚了我的图表本身,并且它接受如下结构:
ObservableList<Data<Timestamp, BigDecimal>>
我的数据存储在一个自定义对象中,就像这样
public class funds{
private long id;
private String userName;
private BigDecimal current;
private Timestamp createdAt;
....constructors/getters/setters....
}
通过每隔1分钟重复一次
funds
为每个用户创建一个Task
对象。我想绘制所有
funds.current
的每小时平均总和图表。因此,通常我会为所有用户汇总每分钟,然后每小时平均。在MySQL中,我可以这样做:
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;
但是在这种情况下,我没有直接的SQL访问权限,必须使用Java。我已经尝试查看流和
Collectors.groupingBy
,但是我无法将其包裹在头上以至于无法获得所需的内容。另外,
Collectors
似乎没有与 BigDecimal 一起使用的任何功能,我需要,因为对财务数据而言,双精度数据非常糟糕。谁能指出我正确的方向?
最佳答案
如果您真的不想使用双打,请尝试以下操作:
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))));