web-dev-qa-db-fra.com

Comment trier une liste <Object> par ordre alphabétique à l'aide du champ Nom de l'objet

J'ai une liste d'objets comme List<Object> p. Je veux trier cette liste par ordre alphabétique en utilisant le champ Nom de l'objet. L'objet contient 10 champs et le champ nom en est un.

if (list.size() > 0) {
    Collections.sort(list, new Comparator<Campaign>() {
        @Override
        public int compare(final Object object1, final Object object2) {
        return String.compare(object1.getName(), object2.getName());
        }
    } );
}

Mais il n'y a rien comme String.compare ..?

93
Saurabh Kumar

D'après votre code, il semble que votre Comparator soit déjà paramétré avec Campaign. Cela ne fonctionnera qu'avec List<Campaign>. En outre, la méthode que vous recherchez est compareTo.

if (list.size() > 0) {
  Collections.sort(list, new Comparator<Campaign>() {
      @Override
      public int compare(final Campaign object1, final Campaign object2) {
          return object1.getName().compareTo(object2.getName());
      }
  });
}

Ou si vous utilisez Java 1.8

list
  .stream()
  .sorted((object1, object2) -> object1.getName().compareTo(object2.getName()));

Un dernier commentaire - il est inutile de vérifier la taille de la liste. Sort travaillera sur une liste vide.

213
Robert B

La méthode la plus correcte pour trier les chaînes alphabétiquement consiste à utiliser Collator, en raison de l'internationalisation. Certaines langues ont un ordre différent en raison de quelques caractères supplémentaires, etc.

   Collator collator = Collator.getInstance(Locale.US);
   if (!list.isEmpty()) {
    Collections.sort(list, new Comparator<Campaign>() {
        @Override
        public int compare(Campaign c1, Campaign c2) {
            //You should ensure that list doesn't contain null values!
            return collator.compare(c1.getName(), c2.getName());
        }
       });
   }

Si vous ne vous souciez pas de l'internationalisation, utilisez string.compare(otherString).

   if (!list.isEmpty()) {
    Collections.sort(list, new Comparator<Campaign>() {
        @Override
        public int compare(Campaign c1, Campaign c2) {
            //You should ensure that list doesn't contain null values!
            return c1.getName().compare(c2.getName());
        }
       });
   }
13
viktor

Regardez Collections.sort() et l'interface Comparator.

La comparaison de chaînes peut être effectuée avec object1.getName().compareTo(object2.getName()) ou object2.getName().compareTo(object1.getName()) (selon le sens du tri souhaité).

Si vous voulez que la sorte soit agnostique à la casse, faites object1.getName().toUpperCase().compareTo(object2.getName().toUpperCase()).

11
tobiasbayer
public class ObjectComparator implements Comparator<Object> {

    public int compare(Object obj1, Object obj2) {
        return obj1.getName().compareTo(obj2.getName());
    }

}

Veuillez remplacer Object par votre classe qui contient le champ name

Usage:

ObjectComparator comparator = new ObjectComparator();
Collections.sort(list, comparator);
7
Jan Vorcak

Utilisation de Java 8 Comparator.comparing :

list.sort(Comparator.comparing(Campaign::getName));
6
Oleksandr Pyrohov

quelque chose comme

  List<FancyObject> theList = … ;
  Collections.sort (theList,
                    new Comparator<FancyObject> ()
                    { int compare (final FancyObject a, final FancyObject d)
                          { return (a.getName().compareTo(d.getName())); }});
2
BRPocock

Voici une version de la réponse de Robert B qui fonctionne pour List<T> et qui est triée en fonction d'une propriété String spécifiée de l'objet à l'aide de Reflection et de bibliothèques tierces.

/**
 * Sorts a List by the specified String property name of the object.
 * 
 * @param list
 * @param propertyName
 */
public static <T> void sortList(List<T> list, final String propertyName) {

    if (list.size() > 0) {
        Collections.sort(list, new Comparator<T>() {
            @Override
            public int compare(final T object1, final T object2) {
                String property1 = (String)ReflectionUtils.getSpecifiedFieldValue (propertyName, object1);
                String property2 = (String)ReflectionUtils.getSpecifiedFieldValue (propertyName, object2);
                return property1.compareToIgnoreCase (property2);
            }
        });
    }
}


public static Object getSpecifiedFieldValue (String property, Object obj) {

    Object result = null;

    try {
        Class<?> objectClass = obj.getClass();
        Field objectField = getDeclaredField(property, objectClass);
        if (objectField!=null) {
            objectField.setAccessible(true);
            result = objectField.get(obj);
        }
    } catch (Exception e) {         
    }
    return result;
}

public static Field getDeclaredField(String fieldName, Class<?> type) {

    Field result = null;
    try {
        result = type.getDeclaredField(fieldName);
    } catch (Exception e) {
    }       

    if (result == null) {
        Class<?> superclass = type.getSuperclass();     
        if (superclass != null && !superclass.getName().equals("Java.lang.Object")) {       
            return getDeclaredField(fieldName, type.getSuperclass());
        }
    }
    return result;
}
2
che javara

Vous pouvez utiliser sortThisBy() de Eclipse Collections :

MutableList<Campaign> list = Lists.mutable.empty();
list.sortThisBy(Campaign::getName);

Si vous ne pouvez pas changer le type de liste de List:

List<Campaign> list = new ArrayList<>();
ListAdapter.adapt(list).sortThisBy(Campaign::getName);

Remarque: je contribue aux collections Eclipse.

2
Nikhil Nanivadekar

Essaye ça:

List< Object> myList = x.getName;
myList.sort(Comparator.comparing(Object::getName));
1

Si vos objets ont un ancêtre commun [soit T], vous devez utiliser List<T> au lieu de List<Object> et implémenter un Comparateur pour ce T, en utilisant le champ de nom.

Si vous n'avez pas d'ancêtre commun, vous pouvez implémenter un compilateur et utiliser réflexion pour extraire le nom. Notez qu'il est dangereux, qu'il n'a pas été suggéré et qu'il présente de mauvaises performances si vous utilisez la réflexion. vous permet d'accéder à un nom de champ sans rien connaître du type réel de l'objet [outre le fait qu'il comporte un champ avec le nom correspondant]

Dans les deux cas, vous devez utiliser Collections.sort () pour trier.

1
amit

Ceci suppose une liste de YourClass au lieu de Object, comme expliqué par amit .

Vous pouvez utiliser ce bit de la bibliothèque Google Guava:

Collections.sort(list, Ordering.natural()
  .onResultOf(new Function<String,YourClass>() {
  public String call(YourClass o) {
     return o.getName();
  }))
  .nullsLast();

Les autres réponses qui mentionnent Comparator ne sont pas incorrectes, car Ordering implémente Comparator. Cette solution est, à mon avis, un peu plus facile, bien que cela puisse être plus difficile si vous êtes débutant et que vous n'êtes pas habitué à utiliser des bibliothèques et/ou une "programmation fonctionnelle".

Copié sans vergogne de cette réponse à ma propre question.

0
Bart van Heukelom

Si vous utilisez un List<Object> pour contenir des objets d'un sous-type comportant un champ de nom (appelons le sous-type NamedObject), vous devez rétrograder les éléments de la liste pour pouvoir accéder au nom. Vous avez 3 options dont la meilleure est la première:

  1. N'utilisez pas un List<Object> en premier lieu si vous pouvez l'aider - conservez vos objets nommés dans un List<NamedObject>
  2. Copiez vos éléments List<Object> dans un List<NamedObject>, vers le bas dans le processus, faites le tri, puis recopiez-les.
  3. Faire le downcasting dans le comparateur

L'option 3 ressemblerait à ceci:

Collections.sort(p, new Comparator<Object> () {
        int compare (final Object a, final Object b) {
                return ((NamedObject) a).getName().compareTo((NamedObject b).getName());
        }
}
0
Mike E

Utiliser une sélection Trier

for(int i = list.size() - 1; i > 0; i--){

  int max = i

  for(int j = 0; j < i; j++){
      if(list.get(j).getName().compareTo(list.get(j).getName()) > 0){
            max= j;
      }
  }

  //make the swap
  Object temp = list.get(i);
  list.get(i) = list.get(max);
  list.get(max) = temp;

}
0
Shizumaru18
if(listAxu.size() > 0){
     Collections.sort(listAxu, new Comparator<Situacao>(){
        @Override
        public int compare(Situacao lhs, Situacao rhs) {            
            return lhs.getDescricao().compareTo(rhs.getDescricao());
        }
    });
 }
0
George Freire