Java Arraylist of object remove elements from an arraylist by date

£可爱£侵袭症+ 提交于 2020-12-27 05:57:08

问题


This is my arraylist

ArrayList<Courses> list = new ArrayList<Courses>();
list.add( new Courses(350,5/20/2020) );
list.add( new Courses(350,4/20/2019 );
list.add( new Courses(350,3/20/2018) );
list.add( new Courses(360,6/20/2020) );
list.add( new Courses(360,5/20/2019) );
list.add( new Courses(370,5/20/2020) );
list.add( new Courses(370,5/19/2018) );
list.add( new Courses(360,4/10/2016) );

public class Courses{
 int coursenum;
 Date date;

}

How can I remove elements so that the arraylist contains only those elements with the latest date?

Should like this;

350, 5/20/2020}
360,6/20/2020}
370, 5/20/2020

回答1:


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

  • Oracle tutorial: Date Time explaining how to use java.time.
  • Java Specification Request (JSR) 310, where java.time was first described.
  • ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
  • Java 8+ APIs available through desugaring
  • ThreeTenABP, Android edition of ThreeTen Backport
  • Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.



回答2:


I will recommend to use LocalDate from java-8, since Date is older version

public class Courses{
    int coursenum;
    LocalDate date;

  }

And then you can use removeIf

list.removeIf(d->d.isBefore(LocalDate.now());



回答3:


Define a key date and remove all courses whose date is before your key date. Provided you have the appropriate getter:

ArrayList<Courses> list = new ArrayList<Courses>();
//populate list

Date someDate = new SimpleDateFormat("MM/dd/yyyy").parse("01/01/2020");

list.removeIf(c -> c.getDate().before(someDate));

Kindly @Randy Casburn has written a minimal yet complete example which I do not want to withhold from the interested reader:

/**
 *
 * @author Randy Casburn
 */
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class Main {

    public static void main(String[] args) {

        Date latest = new Date("1/1/2020");
        List<Courses> list = new ArrayList<>();
        list.add(new Courses(350, new Date("5/20/2020")));
        list.add(new Courses(350, new Date("4/20/2019")));
        list.add(new Courses(350, new Date("3/20/2018")));
        list.add(new Courses(360, new Date("6/20/2020")));
        list.add(new Courses(360, new Date("5/20/2019")));
        list.add(new Courses(370, new Date("5/20/2020")));
        list.add(new Courses(370, new Date("5/19/2018")));
        list.add(new Courses(360, new Date("4/10/2016")));

        list.removeIf(course -> !course.date.after(latest));
        list.forEach(l-> System.out.println(l.date));
    }
}

class Courses {
    int coursenum;
    Date date;
    Courses(int coursenum, Date date){
        this.coursenum = coursenum;
        this.date = date;
    }

}



回答4:


I am attaching my code as an idea for you request. You can play around with it.

public class Courses {

    int courseNum;

    LocalDate date;

    public Courses(int courseNum, LocalDate date) {
        this.courseNum = courseNum;
        this.date = date;
    }

    public int getCourseNum() {
        return courseNum;
    }

    public void setCourseNum(int courseNum) {
        this.courseNum = courseNum;
    }

    public LocalDate getDate() {
        return date;
    }

    public void setDate(LocalDate date) {
        this.date = date;
    }

    @Override public String toString() {
        return new StringJoiner(", ", Courses.class.getSimpleName() + "[", "]")
                .add("courseNum=" + courseNum)
                .add("date=" + date)
                .toString();
    }

public class Main {
  public static void main(String[] args) {
        List<Courses> list = new ArrayList<>();
        list.add(new Courses(350, LocalDate.of(2020, 5, 20)));
        list.add(new Courses(350, LocalDate.of(2019, 4, 20)));
        list.add(new Courses(350, LocalDate.of(2018, 3, 20)));
        list.add(new Courses(360, LocalDate.of(2020, 6, 20)));
        list.add(new Courses(360, LocalDate.of(2019, 5, 20)));
        list.add(new Courses(370, LocalDate.of(2020, 5, 20)));
        list.add(new Courses(370, LocalDate.of(2018, 5, 19)));
        list.add(new Courses(360, LocalDate.of(2016, 4, 10)));

        List<Courses> res = list.stream().filter(c -> c.getDate().getYear() == 2020).collect(Collectors.toList());

        res.forEach(System.out::println);
    }


来源:https://stackoverflow.com/questions/65327012/java-arraylist-of-object-remove-elements-from-an-arraylist-by-date

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!