如何按财务年度使用Java流对项目进行分组

时间:2017-11-08 06:49:33

标签: java java-8 java-stream

假设我有一份月度商店销售清单,以便:

ID, date, amount
1, Jan 2016, $500
2, Feb 2017, $200
3, October 2017, $300

我的财政年度是2016年9月1日到2017年8月31日。换句话说,前两个项目在一个会计年度,另一个在第二个会计年度。实际会计年度是特定于用户的。

我想为每个会计年度创建一个storeSales列表。

到目前为止,我有:

Map<fiscalYearID, List<StoreSale> = storeSales.stream()
                                .collect(
                                    Collectors.groupingBy(
                                        storeSale -> storeSale.getSaleLocalDate()));

问题是上面的代码只会按确切日期分组。我可以添加.getYear()that would only group by year and NOT fiscal year。我还想过为每个会计年度日期范围使用Stream.iterate(),然后将该日期范围内所有商店的商店销售列表列入一个列表,但这样做非常难看,大O值开始很快爬。那将是这样的:

Stream.iterate(startDate, date -> date.plusMonths(1))
        .limit(ChronoUnit.MONTHS.between(startDate, endDate.plusMonths(1)))
        .forEach(
        {
            addToFiscalYear(fiscalYearID, 
                    storeSales.stream().
                            .filter(storeSale -> storeSale.getSaleLocalDate().equals(date))
                            .collect(Collectors.toList());
        });

或类似的东西。我没有太多探索,因为它的大O快速增加,我希望有更好的解决方案......

2 个答案:

答案 0 :(得分:6)

您需要一个接受日期并返回fiscalYearID的方法:

public static fiscalYearID getFiscalYearID (Date date)
{
    // return fiscal year ID matching passed date
}

现在您可以按fiscalYearID进行分组(假设fiscalYearID是一个覆盖equals的类):

Map<fiscalYearID, List<StoreSale>> = 
    storeSales.stream()
              .collect(Collectors.groupingBy(s -> getFiscalYearID (s.getSaleLocalDate())));

答案 1 :(得分:3)

您可以做以下事情:

由于会计年度由用户确定,因此您可以计算会计年度的抵消额。例如,如果会计年度从9月开始,则抵消将为9个月。通过减去9个月,您可以map财政年度到正常年份。使用Java 8 date API应该很容易。然后,您可以使用通常的groupingBy(storeSale -> storeSale.getSaleLocalDate().getYear())对日期进行分组。