Как отсортировать список <Object> по алфавиту с помощью поля имени объекта


103

У меня есть список объектов вроде. List<Object> pЯ хочу отсортировать этот список в алфавитном порядке, используя поле имени объекта. Объект содержит 10 полей, и поле имени является одним из них.

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

Но нет ничего лучше String.compare ..?


3
Как вы собираетесь получить имя? - Objects не имеют имен. Вы имеете в виду использование .toString()?
Мэтт Фенвик

object1и object2должны быть типа Campaign, а функция сравнения - object1.getName().compareTo(object2.getName()).
Барт ван Хекелом

Смешиваешь List<Object>и Comparator<Campaign>. Вы не можете этого сделать. Либо у вас есть List<Object>и, Comparator<Object>либо List<Campaign>иComparator<Campaign>
виктор

Ответы:


231

Из вашего кода похоже, что ваш Comparatorуже параметризован Campaign. Это будет работать только с List<Campaign>. Кроме того, метод, который вы ищете 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());
      }
  });
}

Или, если вы используете Java 1.8

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

И последнее замечание - нет смысла проверять размер списка. Сортировка будет работать с пустым списком.


2
Я думаю, что это лучший ответ, который сводит все к тому, что ищет OP. И, судя по комментариям, я думаю, что он хочет регистр без учета, поэтому просто переключите compareTo на compareToIgnoreCase
Грег Кейс

Незначительное улучшение в первом решении: мы можем сделать if (list.size ()> 1) - поскольку по 1 элементу сортировать не нужно ..
Рами Ямпольский

12
Вы можете использоватьComparator.comparing(Campaign::getName)
Хосе Да Силва

4
list.sort((object1, object2) -> object1. getName().compareTo(object2. getName()));работал у меня
Лукас

1
Попробуйте использовать, sortedList = list.stream().sort((object1, object2) -> object1. getName().compareTo(object2. getName()))..collect(Collectors.toList());чтобы получить новый отсортированный список
Лукас

16

Самый правильный способ сортировки строк по алфавиту - использовать Collatorиз-за интернационализации. Некоторые языки имеют другой порядок из-за небольшого количества дополнительных символов и т. Д.

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

Если вас не волнует интернационализация, используйте 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

Посмотрите Collections.sort()и томуComparator интерфейс.

Сравнение строк может быть сделано с object1.getName().compareTo(object2.getName())или object2.getName().compareTo(object1.getName())( в зависимости от направления сортировки вы желаете).

Если вы хотите, чтобы сортировка была независимой от случая, сделайте это object1.getName().toUpperCase().compareTo(object2.getName().toUpperCase()).


и как вы предлагаете извлечь это поле, вызываемое namaиз Objectтипа? этот ответ неполный.
amit

Извлечение имени зависит от типа объекта. Я предположил, что это просто тип заполнителя. Если вы не можете указать более конкретный тип, вы можете прекратить использовать отражение.
tobiasbayer


7
public class ObjectComparator implements Comparator<Object> {

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

}

Пожалуйста, замените Object своим классом, который содержит поле имени

Использование:

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

Я сделал это, но перед «Поиском» идут «тесты».: (((
Саураб Кумар

если вы хотите о марке обратной сортировки, просто замените obj1.getName().compareTo(obj2.getName()с obj2.getName().compareTo(obj1.getName()в классе компаратора
Ян Vorcak

2

что-то вроде

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

2

Вот версия ответа Роберта Б, которая работает List<T>и сортирует указанное свойство String объекта с использованием Reflection и без сторонних библиотек.

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

Вы можете использовать sortThisBy()из коллекций Eclipse :

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

Если вы не можете изменить тип списка List:

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

Примечание: я участвую в Eclipse Collections.


2

Попробуй это:

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

К вашему сведению, если вы делаете это в Android, для этого требуется как минимум уровень API 24
MSpeed

1

Если у ваших объектов есть общий предок [пусть будет T], вы должны использовать List<T>вместо него List<Object>и реализовать Comparator для этого T, используя поле имени.

Если у вас нет общего предка, вы можете реализовать Comperator и использовать отражение для извлечения имени.Обратите внимание, что использование отражения небезопасно, не рекомендуется и страдает от плохой производительности, но оно позволяет вам получить доступ к имени поля. ничего не зная о фактическом типе объекта [кроме того факта, что у него есть поле с соответствующим именем]

В обоих случаях для сортировки следует использовать Collections.sort () .



0

Это предполагает список YourClassвместо Object, как объяснил amit .

Вы можете использовать этот бит из библиотеки Google Guava:

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

Другие ответы , которые упоминаются Comparatorне неправильно, так как Orderingорудия Comparator. Это решение, на мой взгляд, немного проще, хотя может быть сложнее, если вы новичок и не привыкли использовать библиотеки и / или «функциональное программирование».

Без зазрения совести скопировал этот ответ на свой вопрос.


Я бы так и поступил, но может быть слишком много для ОП.
Грег Кейс

0

Использование выборочной сортировки

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) Зачем ему изобретать велосипед? что не так Collections.sort()? (2) список имеет тип List<Object>и поэтому list.get(j).getName()не будет компилироваться. (3) это решение O (n ^ 2), тогда как использование Collections.sort()является лучшим решением O (nlogn).
amit

0

Если вы используете a List<Object>для хранения объектов подтипа, у которого есть поле имени (позволяет вызвать подтип NamedObject), вам нужно будет уменьшить элементы списка, чтобы получить доступ к имени. У вас есть 3 варианта, лучший из которых - первый:

  1. Не используйте List<Object>в первую очередь, если вы можете помочь - храните свои именованные объекты вList<NamedObject>
  2. Скопируйте свои List<Object>элементы в List<NamedObject>, понижая в процессе, выполните сортировку, затем скопируйте их обратно
  3. Сделайте понижение в компараторе

Вариант 3 будет выглядеть так:

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
Хотите разработать, а не просто сбросить код в вопросе трехлетней давности?
Holloway

0

Ответ @Victor сработал для меня, и я разместил его здесь, в Котлине, на случай, если это будет полезно для кого-то еще, занимающегося 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!!)
   })
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.