Jak sortować listę <Object> alfabetycznie przy użyciu pola Nazwa obiektu


103

Mam listę obiektów, takich jak. List<Object> pChcę posortować tę listę alfabetycznie przy użyciu pola Nazwa obiektu. Obiekt zawiera 10 pól, a jednym z nich jest pole nazwy.

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

Ale nie ma nic takiego jak String.compare ..?


3
Jak zdobędziesz to imię? - Objectnie mają nazw. Czy masz na myśli używanie .toString()?
— Matt Fenwick

object1i object2muszą być typu Campaign, a funkcja porównania jest object1.getName().compareTo(object2.getName()).
— Bart van Heukelom

Miksujesz List<Object>i Comparator<Campaign>. Nie możesz tego zrobić. Albo masz List<Object>i Comparator<Object>lub List<Campaign>iComparator<Campaign>
— viktor

Odpowiedzi:


231

Z twojego kodu wygląda na to, że twój Comparatorjest już sparametryzowany za pomocą Campaign. To zadziała tylko z List<Campaign>. Ponadto metoda, której szukasz, to 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());
      }
  });
}

Lub jeśli używasz Java 1.8

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

Ostatnia uwaga - nie ma sensu sprawdzać rozmiaru listy. Sortowanie będzie działać na pustej liście.


2
Myślę, że jest to najlepsza odpowiedź, która destyluje wszystko do tego, czego szuka PO. A z komentarzy myślę, że chce, aby wielkość liter nie była rozróżniana, więc po prostu przełącz porównanie na porównaćToIgnoreCase
— Greg Case,

Niewielka poprawa w pierwszym rozwiązaniu: możemy zrobić, jeśli (list.size ()> 1) - co do 1 pozycji nie ma potrzeby sortowania ..
— Rami Yampolsky

12
Możesz użyćComparator.comparing(Campaign::getName)
— Jose Da Silva

4
list.sort((object1, object2) -> object1. getName().compareTo(object2. getName()));pracował dla mnie
— Lucas

1
Spróbuj użyć, sortedList = list.stream().sort((object1, object2) -> object1. getName().compareTo(object2. getName()))..collect(Collectors.toList());aby uzyskać nową posortowaną listę
— Lukas,

16

Najbardziej poprawnym sposobem alfabetycznego sortowania ciągów jest użycie Collatorze względu na internacjonalizację. Niektóre języki mają inną kolejność ze względu na kilka dodatkowych znaków itp.

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

Jeśli nie zależy Ci na internacjonalizacji, użyj 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

Spójrz na Collections.sort()i Comparatorinterfejs.

Porównanie ciągów można wykonać za pomocą object1.getName().compareTo(object2.getName())lub object2.getName().compareTo(object1.getName())(w zależności od pożądanego kierunku sortowania).

Jeśli chcesz, aby sortowanie było niezależne od wielkości liter, zrób to object1.getName().toUpperCase().compareTo(object2.getName().toUpperCase()).


i jak sugerujesz wyodrębnienie tego pola wywołanego namaz Objecttypu? ta odpowiedź nie jest kompletna.
— amit

Wyodrębnianie nazw zależy od typu obiektu. Przypuszczam, że to tylko typ zastępczy. Jeśli nie możesz podać bardziej konkretnego typu, możesz skończyć z refleksją.
— tobiasbayer


7
public class ObjectComparator implements Comparator<Object> {

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

}

Zastąp Object swoją klasą, która zawiera pole nazwy

Stosowanie:

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

Zrobiłem to, ale „testy” pojawiają się przed „Wyszukiwanie”.: (((
— Saurabh Kumar

jeśli chcesz o make odwrotnej sortowania, wystarczy wymienić obj1.getName().compareTo(obj2.getName()ze obj2.getName().compareTo(obj1.getName()w klasie porównawczy
— Jan Vorcak

2

coś jak

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

2

Oto wersja odpowiedzi Roberta B, która działa List<T>i sortuje według określonej właściwości String obiektu przy użyciu odbicia i bez bibliotek innych firm

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

Możesz użyć sortThisBy()z kolekcji Eclipse :

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

Jeśli nie możesz zmienić typu listy z List:

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

Uwaga: współtworzę kolekcje Eclipse.


2

Spróbuj tego:

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

Do Twojej wiadomości, jeśli robisz to na Androidzie, wymaga to co najmniej poziomu API 24
— MSpeed

1

Jeśli twoje obiekty mają jakiegoś wspólnego przodka [niech tak będzie T], powinieneś użyć List<T>zamiast tego List<Object>i zaimplementować Komparator dla tego T, używając pola nazwy.

Jeśli nie masz wspólnego przodka, możesz zaimplementować Comperator i użyć odbicia, aby wyodrębnić nazwę. Zauważ, że użycie odbicia jest niebezpieczne, nie sugerowane i ma złe wyniki, ale umożliwia dostęp do nazwy pola nie wiedząc nic o rzeczywistym typie obiektu [poza tym, że ma pole z odpowiednią nazwą]

W obu przypadkach do sortowania należy użyć Collections.sort () .


1

Znalazłem inny sposób na zrobienie tego typu.

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

0

To zakłada listę YourClasszamiast Object, jak wyjaśnił amit .

Możesz użyć tego bitu z biblioteki Google Guava:

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

Pozostałe wymienione odpowiedzi Comparatornie są błędne, ponieważ Orderingnarzędzia Comparator. To rozwiązanie jest moim zdaniem trochę łatwiejsze, chociaż może być trudniejsze, jeśli jesteś początkującym i nie jesteś przyzwyczajony do korzystania z bibliotek i / lub „programowania funkcjonalnego”.

Bezwstydnie skopiowałem tę odpowiedź na moje własne pytanie.


To jest sposób, w jaki bym to zrobił, ale może to być za dużo dla OP.
— Greg Case,

0

Korzystanie z wyboru Sortuj

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) Dlaczego miałby wymyślać koło na nowo? Co w tym złego Collections.sort()? (2) lista jest typu List<Object>i dlatego list.get(j).getName()nie zostanie skompilowana. (3) to rozwiązanie to O (n ^ 2), podczas gdy użycie Collections.sort()jest lepszym rozwiązaniem O (nlogn).
— amit

0

Jeśli używasz a List<Object>do przechowywania obiektów podtypu, który ma pole nazwy (nazwijmy podtyp NamedObject), będziesz musiał obniżyć elementy listy, aby uzyskać dostęp do nazwy. Masz 3 opcje, z których najlepsza jest pierwsza:

  1. Nie używaj List<Object>w pierwszej kolejności a, jeśli możesz temu pomóc - zachowaj nazwane obiekty w aList<NamedObject>
  2. Skopiuj swoje List<Object>elementy do pliku List<NamedObject>, w trakcie zmniejszania, posortuj, a następnie skopiuj je z powrotem
  3. Zrób downcasting w Komparatorze

Opcja 3 wyglądałaby tak:

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
Chcesz rozwinąć, a nie tylko porzucić kod w pytaniu sprzed 3 lat?
— Holloway

0

Odpowiedź @ Victora zadziałała dla mnie i opublikowałem ją ponownie w Kotlinie na wypadek, gdyby była przydatna dla kogoś innego, kto robi Androida.

if (list!!.isNotEmpty()) {
   Collections.sort(
     list,
     Comparator { c1, c2 -> //You should ensure that list doesn't contain null values!
     c1.name!!.compareTo(c2.name!!)
   })
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.