问题描述
我必须在字段 List<Card>
(类型 issueDate
)上过滤 String
,其中卡片要显示到过去 7 年的日期。
我尝试过的解决方案是将 issueDate
字段从 String
解析为 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 及其格式 APISimpleDateFormat
已过时且容易出错。建议完全停止使用它们并切换到 modern date-time API* 。 - 您应该将
issueDate
声明为LocalDate
(或Date
,如果您仍想坚持使用旧 API)而不是String
。但是,无论出于何种原因,如果您仍希望将其保留为String
,您可以更改代码以在 Stream 处理期间仅将其解析为日期类型对象一次(目前,您正在执行两次)。 - 您正在 Stream 处理内部解析
2020-06-08
和2020-08-12
,而它们是静态值,因此它们应该在 Stream 处理之外解析。事实上,如果这些静态日期不是String
,你可以直接创建日期类型的对象,例如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,请检查 Java 8+ APIs available through desugaring 和 How to use ThreeTenABP in Android Project。从 Trail: Date Time 了解有关现代日期时间 API 的更多信息。
,不确定您是否需要在此处解析日期。您的所有日期都是 String
并且具有相同的 yyyy-MM-dd
格式。
在这种特殊情况下,您可以简单地按字典顺序比较字符串:
String from = "2020-06-08";
String to = "2020-08-12";
List<Card> filteredCardList =
cardList.stream()
.filter(card -> card.getIssueDate().compareTo(from) > 0)
.filter(card -> card.getIssueDate().compareTo(to) < 0)
.collect(toList());
或者你对普通的旧循环做同样的事情:
List<Card> filteredCardList = new ArrayList<>();
for(Card card : cardList) {
String date = card.getIssueDate();
if(date.compareTo(from) > 0 && date.compareTo(to) < 0) {
filteredCardList.add(card);
}
}