web-dev-qa-db-fra.com

Comment trier une liste d'objets par leur date (collections 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 rapporte 4 films et me donne les informations suivantes

Java.lang.ArrayIndexOutOfBoundsException: Index de tableau hors limites: 4 sur Java.util.Vector.get (Vector.Java:694) sur 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) à l'adresse entitybeans.jsf.PeliculaController.getPeliculaItems (PeliculaController.Java:257) à Sun.reflect.NativeMethodAccessorImpl.invoke0 (Méthode native) à 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) sur com.Sun.el.parser.AstValue.getValue (AstValue.Java:116) sur com.Sun.el.parser.AstValue.getValue (AstValue.Java:163) ....

16
Ignacio Garat

Dans votre méthode compare, o1 et o2 sont déjà des éléments de la liste movieItems. Donc, vous devriez faire quelque chose comme ça:

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

N'accédez pas et ne modifiez pas la collection dans la Comparator. Le comparateur ne doit être utilisé que pour déterminer quel objet vient avant un autre. Les deux objets à comparer sont fournis sous forme d'arguments.

Date est lui-même comparable, aussi, en utilisant des génériques:

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());
    }
}

Et ne pas instancier le comparateur sur chaque sorte. Utilisation:

private static final MovieComparator comparator = new MovieComparator();
19
Bozho

En Java 8, c'est maintenant aussi simple que:

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

Vous utilisez Comparators de manière incorrecte.

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

J'ajouterais plutôt Commons NullComparator pour éviter quelques problèmes ...

1
neeeeee

En utilisant les fonctionnalités de Java 8, ce sera plus simple.

syntaxe : LIST_NAME.sort (Comparator.comparing (INFO_CLASS :: getMethod));

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

0
user9297677

Vous pouvez utiliser ceci:

Collections.sort(list, org.joda.time.DateTimeComparator.getInstance());
0
Damian Górski