Reputation: 35
I have to filter List<Card>
on the field, issueDate
(type String
), where cards to be shown till last 7 years date.
The solution that I've tried is to parse issueDate
field from String
to Date
and then apply date.after(startDate)
and date.before(endDate)
as below:
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());
Even can't apply for loop as there can be hundreds of cards issued, and it impacts performance by iterating on each card issue date(string to date and check year)
Can anyone suggest a good solution to this problem?
Upvotes: 0
Views: 1790
Reputation: 7279
Not sure you need to parse the dates here. All of your dates are String
and have the same yyyy-MM-dd
format.
In this particular case you could simply compare the strings lexicographically:
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());
or you do the same with plain old loop:
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);
}
}
Upvotes: 0
Reputation: 79425
There are many problems with your code:
java.util
date-time API and their formatting API, SimpleDateFormat
are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API* .issueDate
as LocalDate
(or Date
if you still want to stick to the legacy API) instead of String
. However, for any reason, if you still want to keep it as String
, you can change your code to parse it to a date-type object only once during Stream processing (currently, you are doing it twice).2020-06-08
and 2020-08-12
inside Stream processing whereas they are static values and therefore they should be parsed outside the Stream processing. In fact, if these static dates are not as String
, you can create date-type objects directly e.g. LocalDate start = LocalDate.of(2020, 6, 8)
.These suggestions have been incorporated in the following code:
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());
If you want to collect the Stream into a list of cards, you can do it as follows:
List<Card> cards =
cardList.stream()
.filter(card -> {
LocalDate ld = LocalDate.parse(card.getIssueDate());
return ld.isAfter(start) && ld.isBefore(end);
})
.collect(Collectors.toList());
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project. Learn more about the modern date-time API from Trail: Date Time.
Upvotes: 5