Як сортувати Список <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
Як ви збираєтеся отримати ім’я? - Objectне мають імен. Ви маєте на увазі використання .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
Я думаю, що це найкраща відповідь, яка все перешкоджає тому, що шукає ОП. І з коментарів, я думаю, він хоче нечутливих до регістру, тому просто переключіть на порівнянняTo для порівнянняToIgnoreCase
Грег Кейс

Незначні покращення в першому рішенні: ми можемо зробити, якщо (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типу? ця відповідь не є повною.
Аміт

Вилучення імен залежить від типу об'єкта. Я гадаю, що це просто тип заповнювача. Якщо ви не можете дати більш конкретний тип, ви можете закінчити використання рефлексії.
tobiasbayer


7
public class ObjectComparator implements Comparator<Object> {

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

}

Будь ласка, замініть об’єкт своїм класом, який містить поле імені

Використання:

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.


2

Спробуйте це:

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

FYI, якщо ви робите це в Android, для нього потрібен принаймні рівень 24
MSpeed

1

Якщо у ваших об'єктів є якийсь спільний пращур [хай буде T], ви повинні використовувати List<T>замість нього List<Object>та впроваджувати компаратор для цього T, використовуючи поле імені.

Якщо у вас немає спільного предка, ви можете реалізувати Comperator і використовувати відображення для вилучення імені. Зверніть увагу, що воно є небезпечним, не запропонованим та страждає від поганої продуктивності для використання відображення, але це дозволяє отримати доступ до імені поля не знаючи нічого про фактичний тип об'єкта [окрім того, що у нього є поле з відповідною назвою]

В обох випадках для сортування слід використовувати Collections.sort () .


1

Я знайшов інший спосіб зробити тип.

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

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) рішенням.
Аміт

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
Ви хочете розробити, а не просто демпінговий код у трирічному питанні?
Холлоуей

0

@ Відповідь Віктора працювала на мене і повертала її тут, у Котліні, на випадок, якщо це корисно для когось іншого, що займається 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.