Java8过滤器数组列表与字段日期上的自定义对象
我必须List<Card>在字段issueDate(类型String)上进行过滤,其中卡片要显示到过去 7 年的日期。
我尝试过的解决方案是issueDate从Stringto解析字段Date,然后应用date.after(startDate),date.before(endDate)如下所示:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
cardList.stream()
.map(s->s.getIssueDate())
.filter(dt -> sdf.parse(dt).after(sdf.parse("2020-06-08")) &&
sdf.parse(dt).before(sdf.parse("2020-08-12")))
.collect(Collectors.toList());
甚至不能申请循环,因为可能有数百张卡发行,它通过迭代每个发卡日期(字符串到日期和检查年份)来影响性能
任何人都可以提出一个很好的解决方案来解决这个问题吗?
回答
你的代码有很多问题:
- 该
java.util日期时间API及API格式,SimpleDateFormat都已经过时,而且容易出错。建议完全停止使用它们并切换到现代日期时间 API *。 - 您应该声明
issueDate为LocalDate(或者Date如果您仍想坚持使用旧 API)而不是String. 但是,无论出于何种原因,如果您仍希望将其保留为String,您可以更改代码以在 Stream 处理期间仅将其解析为日期类型对象一次(目前,您正在执行两次)。 - 您正在解析
2020-06-08和2020-08-12内部 Stream 处理,而它们是静态值,因此它们应该在 Stream 处理之外解析。实际上,如果这些静态日期不是 asString,则可以直接创建日期类型的对象,例如LocalDate start = LocalDate.of(2020, 6, 8).
这些建议已包含在以下代码中:
LocalDate start = LocalDate.parse("2020-06-08");
LocalDate end = LocalDate.parse("2020-08-12");
List<LocalDate> dates =
cardList.stream()
.map(card -> LocalDate.parse(card.getIssueDate()))
.filter(ld -> ld.isAfter(start) && ld.isBefore(end))
.collect(Collectors.toList());
如果要将 Stream 收集到卡片列表中,可以按如下方式进行:
List<Card> cards =
cardList.stream()
.filter(card -> {
LocalDate ld = LocalDate.parse(card.getIssueDate());
return ld.isAfter(start) && ld.isBefore(end);
})
.collect(Collectors.toList());
* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用ThreeTen-Backport,它将大部分java.time功能向后移植到 Java 6 和 7。如果您正在为 Android 项目和您的 Android API 工作级别仍然不符合 Java-8,请检查通过 desugaring和How to use ThreeTenABP in Android Project可用的 Java 8+ APIs。从Trail: Date Time 中了解有关现代日期时间 API 的更多信息。