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.