Как отсортировать список объектов по их дате (коллекции java, List <Object>)

private List<Movie> movieItems = null;
public List<Movie> getMovieItems() {
    final int first = 0;
    if (movieItems == null) {
        getPagingInfo();
        movieItems = jpaController.findRange(new int[]{pagingInfo.getFirstItem(), pagingInfo.getFirstItem() + pagingInfo.getBatchSize()});
        Collections.sort(movieItems, new Comparator(){
           public int compare (Object o1, Object o2){
               Date d1 = movieItems.get(((Movie)o1).getMovieId()).getDate();
               Date d2 = movieItems.get(((Movie)o2).getMovieId()).getDate();
               if(d1.before(d2)){
                   movieItems.set(1, (Movie)o1);
                   movieItems.set(2, (Movie)o2);
               }
               return first;
           }
       });
    }
    return movieItems;
}

jpaController возвращает 4 фильма и дает мне следующие

java.lang.ArrayIndexOutOfBoundsException: индекс массива выходит за пределы диапазона: 4   на java.util.Vector.get(Vector.java:694) в entitybeans.jsf.PeliculaController $1.compare(PeliculaController.java:260)   в java.util.Arrays.mergeSort(Arrays.java:1270) в java.util.Arrays.sort(Arrays.java:1210) в java.util.Collections.sort(Collections.java:159) в entitybeans.jsf.PeliculaController.getPeliculaItems(PeliculaController.java:257)   at sun.reflect.NativeMethodAccessorImpl.invoke0 (Нативный метод) в sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)   в sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)   в java.lang.reflect.Method.invoke(Method.java:597) в javax.el.BeanELResolver.getValue(BeanELResolver.java:302) в javax.el.CompositeELResolver.getValue(CompositeELResolver.java:175)   в com.sun.faces.el.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:72)   на com.sun.el.parser.AstValue.getValue(AstValue.java:116) в com.sun.el.parser.AstValue.getValue(AstValue.java:163)....

Ответы

Ответ 1

В вашем методе compare o1 и o2 уже являются элементами в списке movieItems. Итак, вы должны сделать что-то вроде этого:

Collections.sort(movieItems, new Comparator<Movie>() {
    public int compare(Movie m1, Movie m2) {
        return m1.getDate().compareTo(m2.getDate());
    }
});

Ответ 2

Не открывайте и не изменяйте коллекцию в Comparator. Компаратор должен использоваться только для определения того, какой объект находится перед другим. В качестве аргументов приводятся два объекта, которые должны быть сопоставлены.

Date сопоставим, поэтому, используя generics:

class MovieComparator implements Comparator<Movie> {
    public int compare(Movie m1, Movie m2) {
       //possibly check for nulls to avoid NullPointerException
       return m1.getDate().compareTo(m2.getDate());
    }
}

И не создавайте экземпляр компаратора для каждого типа. Использование:

private static final MovieComparator comparator = new MovieComparator();

Ответ 3

В Java 8 это теперь просто:

movieItems.sort(Comparator.comparing(Movie::getDate));

Ответ 4

Вы неправильно используете Comparators.

 Collections.sort(movieItems, new Comparator<Movie>(){
           public int compare (Movie m1, Movie m2){
               return m1.getDate().compareTo(m2.getDate());
           }
       });

Ответ 5

Я бы добавил Commons NullComparator, чтобы избежать некоторых проблем...

Ответ 6

Вы можете использовать это:

Collections.sort(list, org.joda.time.DateTimeComparator.getInstance());

Ответ 7

Используя функциональность Java 8, это будет проще.

синтаксис: LIST_NAME.sort(Comparator.comparing(INFO_CLASS :: getMethod));

пример: movieItems.sort(Comparator.comparing(Movie :: getDate));