Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用java流API对日期进行排序、分组和计数_Java_Java Stream - Fatal编程技术网

使用java流API对日期进行排序、分组和计数

使用java流API对日期进行排序、分组和计数,java,java-stream,Java,Java Stream,如何使用流API解决以下示例 /* * Calculate the total number of Mondays for the specified years grouped by month */ EnumMap<Month, Long> totalMondaysByMonth(int yearSince, int yearUntilInclusive); /* * Issue a list of Fridays on the 13th for the specifie

如何使用流API解决以下示例

/*
 * Calculate the total number of Mondays for the specified years grouped by month
 */
EnumMap<Month, Long> totalMondaysByMonth(int yearSince, int yearUntilInclusive);

/*
 * Issue a list of Fridays on the 13th for the specified years,
 * sorted in ascending order first by year, and second by name of the month
 */
List<LocalDate> friday13s(int yearFrom, int yearUntilInclusive);
/*
*计算按月份分组的指定年份的星期一总数
*/
EnumMap totalMondaysByMonth(整数年自,整数年至结束);
/*
*在指定年份的13日发布一份星期五清单,
*按升序排序,第一个按年份排序,第二个按月份名称排序
*/
列出13号星期五(国际年开始,国际年结束);
我的示例解决方案:

public EnumMap<Month, Long> totalMondaysByMonth(int yearSince, int yearUntilInclusive) {
           return Stream.iterate(LocalDate.of(yearSince, 0, 0), date -> date.plusYears(1))
                   .limit(yearUntilInclusive)
                   .filter(x -> x.getDayOfWeek() == DayOfWeek.MONDAY)
                   .collect(Collectors.groupingBy(LocalDate::getMonth, Collectors.summingLong(???));

}
public EnumMap totalMondaysByMonth(int yearbegin,int yearuntinclusive){
return Stream.iterate(LocalDate.of(yearbeash,0,0),date->date.plusYears(1))
.限额(截止到最后一年)
.filter(x->x.getDayOfWeek()==DayOfWeek.MONDAY)
.collect(Collectors.groupingBy(LocalDate::getMonth,Collectors.summingLong(?));
}
我应该在(Collectors.summingLong(???))中插入什么代码来计算星期一的数量

public List<LocalDate> friday13s(int yearFrom, int yearUntilInclusive) {
    return Stream.iterate(LocalDate.of(yearFrom, 0, 0), date -> date.plusYears(1))
            .limit(yearUntilInclusive)
            .filter(x -> x.getDayOfWeek() == DayOfWeek.FRIDAY || x.getDayOfMonth() == 13)
            .sorted(Comparator.comparing(LocalDate::getYear).thenComparing(LocalDate::getMonth))
            .collect(Collectors.toList());
}
公共列表星期五13s(int yearFrom,int yearuntinclusive){
返回Stream.iterate(LocalDate.of(yearFrom,0,0),date->date.plusYears(1))
.限额(截止到最后一年)
.filter(x->x.getDayOfWeek()==DayOfWeek.FRIDAY | | x.getDayOfMonth()==13)
.sorted(Comparator.comparing(LocalDate::getYear)。然后比较(LocalDate::getMonth))
.collect(Collectors.toList());
}

告诉我如何正确书写。

我只会帮助您修复第一个,您可以理解这一点,也可以修复第二个(几乎相同)

你首先说:

Stream.iterate(LocalDate.of(yearSince, 0, 0), date -> date.plusYears(1))
但是你真的需要在这里重复几年吗?你需要找出
周一
(哪几天是天,不是?)这是这里的主要问题,因为你的“循环”只会发生与年差相同的次数。假设你想要2018-2020年的时间间隔-你打算用你现在拥有的迭代多少次

但是现在您需要考虑何时“停止”这个循环,这就是为什么要使用
limit

 .limit(yearUntilInclusive)
问题是,如果你想正确地迭代
,你真的不知道什么时候停止,是吗?理想情况下,您希望通过使用
谓词来停止,例如:我希望从
2018的第一天开始,到
2020的最后一天停止<代码>限制
不能真正做到这一点(你可以通过从上次的
到第一次的
之间的天数差来实现-我会让你知道怎么做)。或者,我发现将
谓词
takeWhile
一起使用更容易(至少需要java-9)

然后,可以将
收集器.summingLong
设置为
收集器.summingit
(从
32
位整数跳到
64位长度需要很多年)。你需要在那里做什么?对于每一天,你有一个匹配,只需添加一个。简单的“添加一个”也称为
counting
,并且有一个用于该
收集器的收集器。counting()
也可以使用

最后一点是
EnumMap
可以将
Map
作为其构造函数的参数;因此:

public static EnumMap<Month, Integer> totalMondaysByMonth(int yearSince, int yearUntilInclusive) {

    return Stream.iterate(LocalDate.of(yearSince, 1, 1), date -> date.plusDays(1))
                 .takeWhile(date -> date.getYear() <= yearUntilInclusive)
                 .filter(x -> x.getDayOfWeek() == DayOfWeek.MONDAY)
                 .collect(
                     Collectors.collectingAndThen(
                         Collectors.groupingBy(LocalDate::getMonth, Collectors.summingInt(x -> 1)),
                         EnumMap::new
                     )
                 );
}
public static EnumMap totalMondaysByMonth(int yearbegin,int yearuntinclusive){
return Stream.iterate(LocalDate.of(yearbefore,1,1),date->date.plusDays(1))
.takeWhile(date->date.getYear()x.getDayOfWeek()==星期一)
.收集(
收藏,收藏,然后(
Collectors.groupby(LocalDate::getMonth,Collectors.summingit(x->1)),
EnumMap::新建
)
);
}
但你能在这里更有效吗?您可以找到一年中的第一个星期一,然后从该星期一开始迭代几周,而不是几天:

 LocalDate firstMonday = LocalDate.of(yearSince, 1, 1).with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY));
 EnumMap<Month, Integer> right =
        Stream.iterate(firstMonday, date -> date.plusWeeks(1))
              .takeWhile(date -> date.getYear() <= yearUntilInclusive)
              .collect(
                  Collectors.collectingAndThen(
                      Collectors.groupingBy(LocalDate::getMonth, Collectors.summingInt(x -> 1)),
                      EnumMap::new
                  )
              );
localdatefirstmonday=LocalDate.of(yearbefore,1,1).with(temporaladjusts.firstInMonth(DayOfWeek.MONDAY));
枚举映射权=
Stream.iterate(第一个星期一,date->date.plusWeeks(1))
.takeWhile(日期->日期.getYear()1)),
EnumMap::新建
)
);

欢迎来到SO。你的第一句和最后一句不匹配。你的问题到底是什么?请你重新措辞好吗?谢谢,你解释得很好。我想我可以自己完成第二个任务并结束这个主题。当你在做
Stream.iterate时,
.filter(x->x.getDayOfWeek()==DayOfWeek.MONDAY)
还是必需的(firstMonday,date->date.plusWeeks(1))
?请注意,
Stream.iterate(a,b).takeWhile(c)
可以替换为
Stream.iterate(a,c,b)
…和
Collectors.collectionandthen(Collectors.groupingBy(LocalDate::getMonth,Collectors.summingit(x->1)),EnumMap::new)
不仅承担了不必要的复制操作,而且在结果映射为空时可能会失败。所以最好使用
Collectors.groupingBy(LocalDate::getMonth,()->新的EnumMap(Month.class),Collectors.summingit(x->1))
。由于这需要Java 9,因此使用
收集器.summingit(x->1)
而不是
计数()
没有任何优势。OP的原始代码已经有一个
EnumMap
返回类型。@Holger确实可以替换该过滤器。我也同意
流。iterate(a,b,c)
-我想了想,但听起来已经有太多的建议了。不过,这个
EnumMap
建议非常像!更惯用,甚至更高效:
EnumMap right=firstMonday.datesUntil(firstMonday.withYear(yearuntinclusive+1),Period.ofWeeks(1)).collect(collector.groupingBy(LocalDate::getMonth,()->new EnumMap(Month.class),Collectors.counting())