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

Ste*_*ier 2 java java-8 java-stream

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

ID, date, amount
1, Jan 2016, $500
2, Feb 2017, $200
3, October 2017, $300
Run Code Online (Sandbox Code Playgroud)

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

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

到目前为止,我有:

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

问题是上面的代码只会按确切日期分组.我可以添加,.getYear()只能按年份而不是财政年度.我还考虑过使用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());
        });
Run Code Online (Sandbox Code Playgroud)

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

Era*_*ran 6

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

public static fiscalYearID getFiscalYearID (Date date)
{
    // return fiscal year ID matching passed date
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • @StephaneGrenier你的意思是大O值大吗?它应该是线性时间(输入列表只被遍历一次). (4认同)
  • 我不认为,`date`是一个`Date`,因为问题中的所有内容都像`java.time` API.所以它可能是"Temporal"或"LocalDate"...... (3认同)
  • @StephaneGrenier为什么实现该方法不是很简单?从日期获得月份,如果> = 9月,则返回下一年,否则返回当前年份. (2认同)
  • @Eran更不用说我希望你在代码中需要像这样的方法.实际上是一个`FiscalYear`构造函数. (2认同)