Java 1.7 and java.time through ThreeTen Backport
ArrayList<Course> list = new ArrayList<>();
list.add( new Course(350, "5/20/2020") );
list.add( new Course(350, "4/20/2019") );
list.add( new Course(350, "3/20/2018") );
list.add( new Course(360, "6/20/2020") );
list.add( new Course(360, "5/20/2019") );
list.add( new Course(370, "5/20/2020") );
list.add( new Course(370, "5/19/2018") );
list.add( new Course(360, "4/10/2016") );
// Find latest date for each course number
Map<Integer, LocalDate> latestDates = new HashMap<>();
for (Course currentCourse : list) {
LocalDate latestHitherto = latestDates.get(currentCourse.getCourseNumber());
if (latestHitherto == null || currentCourse.getDate().isAfter(latestHitherto)) {
latestDates.put(currentCourse.getCourseNumber(), currentCourse.getDate());
}
}
// Remove courses that haven’t got the latest date
Iterator<Course> courseIterator = list.iterator();
while (courseIterator.hasNext()) {
Course currentCourse = courseIterator.next();
if (currentCourse.getDate().isBefore(latestDates.get(currentCourse.getCourseNumber()))) {
courseIterator.remove();
}
}
// Print result
for (Course currentCourse : list) {
System.out.format("%3d %s%n",
currentCourse.getCourseNumber(),
currentCourse.getDate().format(Course.dateFormatter));
}
Output from this snippet was:
350 5/20/2020
360 6/20/2020
370 5/20/2020
I ran on jdk1.7.0_67. I had added ThreeTen Backport 1.3.6. See the link below.
Here is the Course
class I used:
public class Course {
public static final DateTimeFormatter dateFormatter
= DateTimeFormatter.ofPattern("M/d/u");
private int courseNumber;
private LocalDate date;
public Course(int courseNumber, String dateString) {
this.courseNumber = courseNumber;
this.date = LocalDate.parse(dateString, dateFormatter);
}
public int getCourseNumber() {
return courseNumber;
}
public LocalDate getDate() {
return date;
}
}
If you insist on using java.util.Date
— a poorly designed and long outdated class — (1) I would not understand why you would, (2) you can probably modify my code to use Date
instead.
Stream version
You may want consider upgrading your Java version. Java 15 is out, and an early access edition of Java 16. Already in Java 8 comes streams. They will allow you to obtain the same in much fewer lines of code:
Collection<Course> filteredCourses = list.stream()
.collect(Collectors.groupingBy(Course::getCourseNumber,
Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparing(Course::getDate)),
Optional::orElseThrow)))
.values();
List<Course> filteredList = new ArrayList<>(filteredCourses);
filteredList.forEach(c -> System.out.format(
"%3d %s%n", c.getCourseNumber(), c.getDate().format(Course.dateFormatter)));
370 5/20/2020
360 6/20/2020
350 5/20/2020
As the code stands it doesn’t give the same order of courses in the resulting list, and it requires Java 10 (the overlaoded no-arg orElseThrow
method was introduced there). Even if you require the same order, streams will still be extremely helpful.
Question: Can that work on Java 1.7?
java.time works nicely on both older and newer Android devices. It just requires at least Java 6.
- In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
- In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
- On older Android either use desugaring or the Android edition of ThreeTen Backport. It’s called ThreeTenABP. In the latter case make sure you import the date and time classes from
org.threeten.bp
with subpackages.
Links