使用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))));

09-19 13:01