Cómo ordenar una lista <Objeto> alfabéticamente usando el campo de nombre de objeto


103

Tengo una lista de objetos como List<Object> p. Quiero ordenar esta lista alfabéticamente usando el campo de nombre de objeto. El objeto contiene 10 campos y el campo de nombre es uno de ellos.

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

Pero no hay nada como String.compare ..?


3
¿Cómo vas a conseguir el nombre? - ObjectNo tengo nombres. ¿Te refieres a usar .toString()?
Matt Fenwick

object1y object2debe ser de tipo Campaign, y la función de comparación es object1.getName().compareTo(object2.getName()).
Bart van Heukelom

Mezclas List<Object>y Comparator<Campaign>. No puedes hacer eso. O tienes List<Object>y Comparator<Object>o List<Campaign>eComparator<Campaign>
Viktor

Respuestas:


231

A partir de su código, parece que Comparatorya está parametrizado con Campaign. Esto solo funcionará con List<Campaign>. Además, el método que está buscando es 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 si está utilizando Java 1.8

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

Un comentario final: no tiene sentido verificar el tamaño de la lista. Ordenar funcionará en una lista vacía.


2
Creo que esta es la mejor respuesta que destila todo en lo que está buscando el OP. Y a partir de los comentarios, creo que quiere que no se distinga entre mayúsculas y minúsculas, así que simplemente cambie el compareTo a compareToIgnoreCase
Greg Case

Mejora menor en la primera solución: podemos hacer if (list.size ()> 1) - como para 1 elemento no es necesario ordenar ..
Rami Yampolsky

12
Puede usarComparator.comparing(Campaign::getName)
Jose Da Silva

4
list.sort((object1, object2) -> object1. getName().compareTo(object2. getName()));trabajó para mí
Lucas

1
Intente usar sortedList = list.stream().sort((object1, object2) -> object1. getName().compareTo(object2. getName()))..collect(Collectors.toList());para obtener una nueva lista ordenada
Lukas

16

La forma más correcta de ordenar alfabéticamente cadenas es usar Collator, debido a la internacionalización. Algunos idiomas tienen un orden diferente debido a algunos caracteres adicionales, 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 no le importa el uso de la internacionalización 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

Echar un vistazo a Collections.sort(), y elComparator interfaz.

La comparación de cadenas se puede realizar con object1.getName().compareTo(object2.getName())o object2.getName().compareTo(object1.getName())(según la dirección de clasificación que desee).

Si desea que el tipo sea independiente del caso, hágalo object1.getName().toUpperCase().compareTo(object2.getName().toUpperCase()).


y ¿cómo sugiere extraer ese campo llamado namadel Objecttipo? esta respuesta no es completa.
amit

La extracción de nombres depende del tipo de objeto. Supuse que es solo un tipo de marcador de posición. Si no puede dar un tipo más concreto, puede terminar usando la reflexión.
tobiasbayer


7
public class ObjectComparator implements Comparator<Object> {

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

}

Reemplace el objeto con su clase que contiene el campo de nombre

Uso:

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

Hice esto, pero las "pruebas" vienen antes de "Buscar".: (((
Saurabh Kumar

si desea hacer una clasificación inversa, simplemente reemplace obj1.getName().compareTo(obj2.getName()con obj2.getName().compareTo(obj1.getName()en la clase de comparador
Jan Vorcak

2

algo como

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

2

Aquí hay una versión de la respuesta de Robert B que funciona List<T>y ordena por una propiedad String especificada del objeto usando Reflection y sin bibliotecas de terceros

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

Puede usar sortThisBy()de Eclipse Collections :

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

Si no puede cambiar el tipo de lista de List:

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

Nota: Soy colaborador de Eclipse Collections.


2

Prueba esto:

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

Para su información, si está haciendo esto en Android, requiere al menos un nivel de API 24
MSpeed

1

Si sus objetos tienen algún ancestro común [déjelo ser T], debe usar en List<T>lugar de List<Object>e implementar un Comparador para esta T, usando el campo de nombre.

Si no tiene un ancestro común, puede implementar un Comperator y usar la reflexión para extraer el nombre.Tenga en cuenta que no es seguro, no se sugiere y tiene un mal rendimiento para usar la reflexión, pero le permite acceder a un nombre de campo. sin saber nada sobre el tipo real del objeto [además del hecho de que tiene un campo con el nombre relevante]

En ambos casos, debe usar Collections.sort () para ordenar.


1

Encontré otra forma de escribir.

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

0

Esto supone una lista de en YourClasslugar de Object, como explica amit .

Puede usar este bit de la biblioteca de Google Guava:

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

Las otras respuestas que mencionan Comparatorno son incorrectas, ya que Orderingimplementa Comparator. Esta solución es, en mi opinión, un poco más fácil, aunque puede ser más difícil si eres un principiante y no estás acostumbrado a usar bibliotecas y / o "programación funcional".

Copiado descaradamente de esta respuesta a mi propia pregunta.


Esta es la forma en que lo haría, pero puede ser demasiado para el OP.
Greg Case

0

Usando una selección Ordenar

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) ¿Por qué iba a reinventar la rueda? lo que está mal con el Collections.sort()? (2) la lista es de tipo List<Object>y, por list.get(j).getName()lo tanto , no se compilará. (3) esta solución es O (n ^ 2), mientras que usar Collections.sort()es una mejor solución O (nlogn).
amit

0

Si está utilizando List<Object>para contener objetos de un subtipo que tiene un campo de nombre (llamemos al subtipo NamedObject), necesitará abatir los elementos de la lista para acceder al nombre. Tienes 3 opciones, la mejor de las cuales es la primera:

  1. List<Object>En primer lugar, no use un si puede evitarlo; mantenga los objetos con nombre en unList<NamedObject>
  2. Copie sus List<Object>elementos en un List<NamedObject>, reduciendo en el proceso, haga la clasificación y luego cópielos de nuevo
  3. Hacer el downcasting en el comparador

La opción 3 se vería así:

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
¿Le gustaría elaborar en lugar de simplemente descargar el código en una pregunta de 3 años?
Holloway

0

La respuesta de @ Victor funcionó para mí y volver a publicarla aquí en Kotlin en caso de que sea útil para otra persona que usa 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!!)
   })
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.