我需要从每个提到的月份的给定日期数组中提取最少的日期。
示例-日期格式为dd / MM / yyyy 以下是示例输入
04/11/2019, 11/11/2019, 18/11/2019, 25/11/2019, 02/12/2019, 09/12/2019,
06/01/2020, 03/02/2020, 10/02/2020, 17/02/2020, 24/02/2020, 02/03/2020,
09/03/2020, 16/03/2020, 23/03/2020, 30/03/2020, 06/04/2020, 13/04/2020,
20/04/2020, 27/04/2020
我需要从每个月获取最少的日期:
输出类似-
04/11/2019, 02/12/2019, 06/01/2020, 03/02/2020, 02/03/2020, 06/04/2020
有人可以帮忙吗?
答案 0 :(得分:5)
如果您使用的是Java-8,则可以使用:
List<LocalDate> collect = Stream.of(strings)
.map(s -> LocalDate.parse(s, format)) // convert your strings to LocalDate
.collect(Collectors.groupingBy(YearMonth::from)) // group by year and month
.values().stream()
.map(a -> a.stream().sorted().limit(1).findFirst().get())
.sorted()
.collect(Collectors.toList()); // collect the results
输出
[2019-11-04, 2019-12-02, 2020-01-06, 2020-02-03, 2020-03-02, 2020-04-06]
答案 1 :(得分:3)
public List<LocalDate> filterDates(List<LocalDate> dates) {
return dates.stream()
.collect(Collectors.groupingBy(YearMonth::from))
.values()
.stream()
.map(Collections::min) // .map(Collections::max)
.collect(Collectors.toList());
}
您可以使用以下内容代替.map(Collections::min)
:
.map(list -> {
list.sort(Comparator.naturalOrder());
return list.get(0);
})
或者:
.map(list -> list.stream().max(Comparator.naturalOrder()))
答案 2 :(得分:3)
已经有很多好的答案。除了这些,我想补充:
LocalDate
个对象。如果您收到字符串输入,请先解析它,然后再添加到列表中。在Java 10或更高版本中:
List<LocalDate> input = List.of(LocalDate.of(2019, 11, 4),
LocalDate.of(2019, 11, 11), LocalDate.of(2019, 11, 18),
LocalDate.of(2019, 11, 25), LocalDate.of(2019, 12, 2),
LocalDate.of(2019, 12, 9), LocalDate.of(2020, 1, 6),
LocalDate.of(2020, 2, 3), LocalDate.of(2020, 2, 10),
LocalDate.of(2020, 2, 17), LocalDate.of(2020, 2, 24),
LocalDate.of(2020, 3, 2), LocalDate.of(2020, 3, 9),
LocalDate.of(2020, 3, 16), LocalDate.of(2020, 3, 23),
LocalDate.of(2020, 3, 30), LocalDate.of(2020, 4, 6),
LocalDate.of(2020, 4, 13), LocalDate.of(2020, 4, 20),
LocalDate.of(2020, 4, 27));
List<LocalDate> minDatePerMonth = input.stream()
.collect(Collectors.groupingBy(YearMonth::from, Collectors.minBy(Comparator.naturalOrder())))
.values()
.stream()
.map(Optional::orElseThrow)
.sorted()
.collect(Collectors.toList());
我正在使用Collectors.groupingBy
的重载版本,该版本接受下游收集器。 groupingBy
会生成一个映射,但不是由列表收集映射值,而是由下游收集器生成。在这种情况下,Collectors.minBy
会产生Optional<LocalDate>
。而且,由于groupingBy
至少要有一个日期才能创建地图条目,因此我们知道Optional
不能为空。
当然,我们希望为用户提供格式正确的输出。我们以这种方式产生这种结果:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/uuuu");
String output = minDatePerMonth.stream()
.map(formatter::format)
.collect(Collectors.joining(", "));
System.out.println(output);
04/11 / 2019、02 / 12 / 2019、06 / 01 / 2020、03 / 02 / 2020、02 / 03 / 2020、06 / 04/2020
在Java 9中
no-arg Optional.orElseThrow
是Java 10中引入的。在Java 8和9中,您可以使用例如:
.map(old -> old.orElseThrow(() -> new IllegalStateException("This can’t happen")))
在Java 8中
List.of
是Java 9中引入的。但是您说您已经有了列表,因此我考虑了如何在问题之外对其进行初始化。我相信读者可以根据需要找到在Java 8中对其进行初始化的方法。
答案 3 :(得分:1)
这是您需要做的一个顺序
这是您的算法。我将把实施留给您。
答案 4 :(得分:1)
// localDates是LocalDate的列表。您可以将其转换。
localDates.stream().forEach(localDate -> {
Integer month = localDate.getMonthValue();
if (localDateMap.containsKey(month)){
if(localDate.isBefore(localDateMap.get(month))){
localDateMap.put(month,localDate);
}
}else{
localDateMap.put(month,localDate);
}
});
然后从地图中获取所有值。