Come ordinare alfabeticamente un elenco <Oggetto> utilizzando il campo Nome oggetto


103

Ho un elenco di oggetti come List<Object> p. Voglio ordinare questo elenco in ordine alfabetico utilizzando il campo Nome oggetto. L'oggetto contiene 10 campi e il campo nome è uno di questi.

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

Ma non c'è niente come String.compare ..?


3
Come hai intenzione di ottenere il nome? - ObjectNon ho nomi. Intendi usare .toString()?
Matt Fenwick

object1e object2devono essere di tipo Campaign, e la funzione di confronto lo è object1.getName().compareTo(object2.getName()).
Bart van Heukelom

Mescoli List<Object>e Comparator<Campaign>. Non puoi farlo. O hai List<Object>e Comparator<Object>o List<Campaign>eComparator<Campaign>
viktor

Risposte:


231

Dal tuo codice, sembra che il tuo Comparatorsia già parametrizzato con Campaign. Funzionerà solo con List<Campaign>. Inoltre, il metodo che stai cercando è 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());
      }
  });
}

O se stai usando Java 1.8

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

Un ultimo commento: non ha senso controllare la dimensione dell'elenco. L'ordinamento funzionerà su un elenco vuoto.


2
Penso che questa sia la risposta migliore che riassume tutto ciò che l'OP sta cercando. E dai commenti, penso che voglia fare distinzione tra maiuscole e minuscole, quindi basta cambiare il confrontoTo per confrontareToIgnoreCase
Greg Case

Miglioramento minore nella prima soluzione: possiamo fare se (list.size ()> 1) - come per 1 elemento non è necessario ordinare ..
Rami Yampolsky

12
Puoi usareComparator.comparing(Campaign::getName)
Jose Da Silva

4
list.sort((object1, object2) -> object1. getName().compareTo(object2. getName()));ha funzionato per me
Lucas

1
Prova a utilizzare sortedList = list.stream().sort((object1, object2) -> object1. getName().compareTo(object2. getName()))..collect(Collectors.toList());per ottenere un nuovo elenco ordinato
Lukas

16

Il modo più corretto per ordinare alfabeticamente le stringhe è quello di utilizzare Collator, a causa dell'internazionalizzazione. Alcune lingue hanno un ordine diverso a causa di pochi caratteri extra ecc.

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

Se non ti interessa l'internazionalizzazione usa 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());
        }
       });
   }

11

Dai un'occhiata a Collections.sort()e l' Comparatorinterfaccia.

Il confronto delle stringhe può essere eseguito con object1.getName().compareTo(object2.getName())o object2.getName().compareTo(object1.getName())(a seconda della direzione di ordinamento desiderata).

Se vuoi che il tipo sia indipendente dal caso, fallo object1.getName().toUpperCase().compareTo(object2.getName().toUpperCase()).


e come suggerisci di estrarre quel campo chiamato namadal Objecttipo? questa risposta non è completa.
amit

L'estrazione del nome dipende dal tipo di oggetto. Suppongo sia solo un tipo di segnaposto. Se non puoi dare un tipo più concreto, potresti finire con la riflessione.
tobiasbayer


7
public class ObjectComparator implements Comparator<Object> {

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

}

Sostituisci Object con la tua classe che contiene il campo del nome

Uso:

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

L'ho fatto ma poi "test" viene prima di "Ricerca".: (((
Saurabh Kumar

se vuoi fare l'ordinamento inverso, sostituisci semplicemente obj1.getName().compareTo(obj2.getName()con obj2.getName().compareTo(obj1.getName()nella classe di confronto
Jan Vorcak

2

qualcosa di simile a

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

2

Ecco una versione della risposta di Robert B che funziona List<T>e ordina in base a una proprietà String specificata dell'oggetto utilizzando Reflection e nessuna libreria di terze parti

/**
 * 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

È possibile utilizzare sortThisBy()da Eclipse Collections :

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

Se non puoi modificare il tipo di elenco da List:

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

Nota: contribuisco alle collezioni Eclipse.


2

Prova questo:

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

Cordiali saluti, se lo stai facendo su Android, richiede almeno il livello API 24
MSpeed

1

Se i tuoi oggetti hanno qualche antenato comune [lascia che sia T] dovresti usare al List<T>posto di List<Object>e implementare un comparatore per questa T, usando il campo nome.

Se non si dispone di un antenato comune, è possibile implementare un Comperator e utilizzare la reflection per estrarre il nome.Nota che non è sicuro, non è suggerito e soffre di cattive prestazioni per utilizzare la reflection, ma ti consente di accedere a un nome di campo senza sapere nulla sul tipo effettivo dell'oggetto [oltre al fatto che ha un campo con il nome pertinente]

In entrambi i casi, dovresti usare Collections.sort () per ordinare.


1

Ho trovato un altro modo per fare il tipo.

if(listAxu.size() > 0){
    Collections.sort(listAxu, Comparator.comparing(IdentityNamed::getDescricao));
}

0

Questo presuppone un elenco di YourClassinvece di Object, come spiegato da amit .

Puoi usare questo bit dalla libreria di Google Guava:

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

Le altre risposte che menzionano Comparatornon sono corrette, poiché Orderingimplementa Comparator. Questa soluzione è, a mio parere, un po 'più semplice, anche se potrebbe essere più difficile se sei un principiante e non sei abituato a usare le librerie e / o la "programmazione funzionale".

Copiato spudoratamente da questa risposta sulla mia stessa domanda.


Questo è il modo in cui lo farei, ma potrebbe essere troppo per l'OP.
Greg Case

0

Utilizzando una selezione Ordina

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;

}

(1) Perché avrebbe reinventato la ruota? cosa c'è che non va Collections.sort()? (2) l'elenco è di tipo List<Object>e quindi list.get(j).getName()non verrà compilato. (3) questa soluzione è O (n ^ 2), mentre l'utilizzo Collections.sort()è una soluzione migliore O (nlogn).
amit

0

Se stai usando a List<Object>per contenere oggetti di un sottotipo che ha un campo nome (chiamiamo il sottotipo NamedObject), dovrai abbassare gli elementi dell'elenco per accedere al nome. Hai 3 opzioni, la migliore delle quali è la prima:

  1. Non usare a List<Object>in primo luogo se puoi evitarlo: tieni gli oggetti con nome in un fileList<NamedObject>
  2. Copia i tuoi List<Object>elementi in un List<NamedObject>, abbattendo nel processo, esegui l'ordinamento, quindi copiali di nuovo
  3. Esegui il downcasting nel comparatore

L'opzione 3 sarebbe simile a questa:

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

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

1
Ti interessa elaborare piuttosto che scaricare il codice in una domanda vecchia di 3 anni?
Holloway

0

La risposta di @ Victor ha funzionato per me e ripubblicandola qui a Kotlin nel caso fosse utile a qualcun altro che utilizza Android.

if (list!!.isNotEmpty()) {
   Collections.sort(
     list,
     Comparator { c1, c2 -> //You should ensure that list doesn't contain null values!
     c1.name!!.compareTo(c2.name!!)
   })
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.