Как отсортировать список объектов по их дате (коллекции 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));