Nesnelerin listesi bazı özelliklere göre nasıl sıralanır


148

Basit dersim var

public class ActiveAlarm {
    public long timeStarted;
    public long timeEnded;
    private String name = "";
    private String description = "";
    private String event;
    private boolean live = false;
}

ve List<ActiveAlarm>aleyhte. timeStartedDaha sonra artan sırada nasıl sıralayabilirim timeEnded? Biri yardım edebilir mi? C ++ 'da genel algoritma ve aşırı yükleme operatörü <biliyorum, ancak Java'da yeniyim.


Bu gönderideki @ Yishai tarafından verilen yanıt, karşılaştırıcı zincirleme kullanarak özel sıralama ve gruplandırılmış sıralama (çoklu bağımsız değişkenler) için numaralamanın zarif kullanımını göstermektedir.
gunalmel

Yanıtlar:


142

Ya ActiveAlarmuygulama yapın Comparable<ActiveAlarm>ya da Comparator<ActiveAlarm>ayrı bir sınıfta gerçekleştirin. Sonra ara:

Collections.sort(list);

veya

Collections.sort(list, comparator);

Genel olarak, bu uygulamaya iyi bir fikirdir Comparable<T>aksi ... tek bir "doğal" sıralama düzeni varsa (eğer varsa gerçekleşmesi belirli bir sırada sıralamak istiyorum, ama aynı derecede kolaylıkla farklı bir isteyebilirsiniz) projesinin hayata daha iyidir Comparator<T>. Dürüst olmak gerekirse, bu özel durum her iki şekilde de olabilir ... ama muhtemelen daha esnek Comparator<T>seçeneğe bağlı kalırım.

EDIT: Örnek uygulama:

public class AlarmByTimesComparer implements Comparator<ActiveAlarm> {
  @Override
  public int compare(ActiveAlarm x, ActiveAlarm y) {
    // TODO: Handle null x or y values
    int startComparison = compare(x.timeStarted, y.timeStarted);
    return startComparison != 0 ? startComparison
                                : compare(x.timeEnded, y.timeEnded);
  }

  // I don't know why this isn't in Long...
  private static int compare(long a, long b) {
    return a < b ? -1
         : a > b ? 1
         : 0;
  }
}

1
Bu karşılaştırma () işlevi Long'da değildir çünkü uygulama daha da önemsizdir: döndür a - b;
papercrane

5
@papercrane: Hayır, taşma nedenlerinden dolayı başarısız olur. Düşünün a = Long.MIN_VALUE, b = 1.
Jon Skeet

3
API 19'dan itibaren (KitKat) Long artık bir.compare
Martin Marconcini'ye sahip

125

Kullanma Comparator

Örneğin:

class Score {

    private String name;
    private List<Integer> scores;
    // +accessor methods
}

    Collections.sort(scores, new Comparator<Score>() {

        public int compare(Score o1, Score o2) {
            // compare two instance of `Score` and return `int` as result.
            return o2.getScores().get(0).compareTo(o1.getScores().get(0));
        }
    });

Java 8'den itibaren, Comparator örneğini temsil etmek için basitçe lambda ifadesini kullanabilirsiniz.

Collections.sort(scores, (s1, s2) -> { /* compute and return int */ });

1
Ne yapar compareTo()? Nereden geliyor? Onu nerede tanımlamalıyım?
Asqiir

1
@ Asqiir getScores(), scoresbir List<Integer>. Yaptığınızda getScores().get(0)bir Integernesne alırsınız . yöntemi Integerzaten compareTo(anotherInteger)uyguladı, onu tanımlamanıza gerek yok.
walen

get (0) nedir?
Ali Khaki

1
Teşekkürler bir cazibe gibi çalışır (.get (0) kısmı olmadan kullanıyorum). Sırayı nasıl tersine çevirebilirim?

57

JAVA 8 ve Yukarıdaki Cevap (Lambda İfadeleri Kullanarak)

Java 8'de, bunu daha da kolaylaştırmak için Lambda ifadeleri tanıtıldı! Tüm iskelesi ile bir Comparator () nesnesi oluşturmak yerine, aşağıdaki gibi basitleştirebilirsiniz: (Nesnenizi örnek olarak kullanarak)

Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.timeStarted-a2.timeStarted);

hatta daha kısa:

Collections.sort(list, Comparator.comparingInt(ActiveAlarm ::getterMethod));

Bu tek ifade aşağıdakine eşdeğerdir:

Collections.sort(list, new Comparator<ActiveAlarm>() {
    @Override
    public int compare(ActiveAlarm a1, ActiveAlarm a2) {
        return a1.timeStarted - a2.timeStarted;
    }
});

Lambda ifadelerini yalnızca kodun ilgili kısımlarını (yöntem imzası ve döndürülenleri) yerleştirmenizi gerektiriyor olarak düşünün.

Sorunuzun bir başka kısmı, birden çok alanla nasıl karşılaştırılacağıydı. Bunu Lambda ifadeleriyle yapmak için, .thenComparing()işlevi iki karşılaştırmayı tek bir karşılaştırmada etkili bir şekilde birleştirmek için kullanabilirsiniz :

Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.timeStarted-a2.timeStarted             
       .thenComparing ((ActiveAlarm a1, ActiveAlarm a2) -> a1.timeEnded-a2.timeEnded)
);

Yukarıdaki kod, listeyi önce timeStartedve sonra timeEnded(aynı olan kayıtlar için) göre sıralayacaktır timeStarted.

Son bir not: 'long' veya 'int' ilkelleri karşılaştırmak kolaydır, sadece birini diğerinden çıkarabilirsiniz. Nesneleri karşılaştırıyorsanız ('Uzun' veya 'Dize'), onların yerleşik karşılaştırmasını kullanmanızı öneririm. Misal:

Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.name.compareTo(a2.name) );

DÜZENLEME: Bana .thenComparing()işlev gösterdiği için Lukas Eder'e teşekkürler .


4
Yeni Java 8 API'sini Comparator.comparing().thenComparing()
Lukas Eder

1
Geri dönen farka dikkat edin. Taşma durumunda yanlış sonuç alabilirsiniz.
krzychu

2
Bu, yine açık bir doğal düzene sahip olmadığınızı varsayarak, IMHO'nun daha kolay sıralama yöntemidir. Artık aramanıza da gerek Collectionsyok, doğrudan listeden arama yapabilirsiniz. Örneğin:myList.sort(Comparator.comparing(Address::getZipCode).thenComparing(Compartor.comparing(Address::getStreetName));
CeePlusPlus

hatta daha kısa süreli kullanım: - list.sort (Comparator.comparingDouble (ActiveAlarm :: getterMethod));
Tharindu Eranga

20

Listeyi iki yoldan biriyle sıralayabiliriz:

1. Karşılaştırıcıyı Kullanma : Sıralama mantığını birden çok yerde kullanmak gerektiğinde Sıralama mantığını tek bir yerde kullanmak istiyorsanız, aşağıdaki gibi anonim bir iç sınıf yazabilir veya karşılaştırıcıyı çıkarabilir ve birden çok yerde kullanabilirsiniz.

  Collections.sort(arrayList, new Comparator<ActiveAlarm>() {
        public int compare(ActiveAlarm o1, ActiveAlarm o2) {
            //Sorts by 'TimeStarted' property
            return o1.getTimeStarted()<o2.getTimeStarted()?-1:o1.getTimeStarted()>o2.getTimeStarted()?1:doSecodaryOrderSort(o1,o2);
        }

        //If 'TimeStarted' property is equal sorts by 'TimeEnded' property
        public int doSecodaryOrderSort(ActiveAlarm o1,ActiveAlarm o2) {
            return o1.getTimeEnded()<o2.getTimeEnded()?-1:o1.getTimeEnded()>o2.getTimeEnded()?1:0;
        }
    });

'Long' yerine 'Long' kullanmış olsaydık, özellikler için boş kontrol yapabiliriz.

2. Comparable (doğal sıralama) kullanma : Sıralama algoritması her zaman bir özelliğe bağlıysa: 'Comparable' uygulayan bir sınıf yazın ve aşağıda tanımlandığı gibi 'CompareTo' yöntemini geçersiz kılın

class ActiveAlarm implements Comparable<ActiveAlarm>{

public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;

public ActiveAlarm(long timeStarted,long timeEnded) {
    this.timeStarted=timeStarted;
    this.timeEnded=timeEnded;
}

public long getTimeStarted() {
    return timeStarted;
}

public long getTimeEnded() {
    return timeEnded;
}

public int compareTo(ActiveAlarm o) {
    return timeStarted<o.getTimeStarted()?-1:timeStarted>o.getTimeStarted()?1:doSecodaryOrderSort(o);
}

public int doSecodaryOrderSort(ActiveAlarm o) {
    return timeEnded<o.getTimeEnded()?-1:timeEnded>o.getTimeEnded()?1:0;
}

}

Doğal sıralamaya göre sıralamak için sıralama yöntemini çağırın

Collections.sort(list);

7

Java8 + 'da bu aşağıdaki gibi tek satırda yazılabilir:

collectionObjec.sort(comparator_lamda) veya comparator.comparing(CollectionType::getterOfProperty)

kod:

ListOfActiveAlarmObj.sort((a,b->a.getTimeStarted().compareTo(b.getTimeStarted())))
 

veya

ListOfActiveAlarmObj.sort(Comparator.comparing(ActiveAlarm::getTimeStarted))

5
public class ActiveAlarm implements Comparable<ActiveAlarm> {
    public long timeStarted;
    public long timeEnded;
    private String name = "";
    private String description = "";
    private String event;
    private boolean live = false;

    public int compareTo(ActiveAlarm a) {
        if ( this.timeStarted > a.timeStarted )
            return 1;
        else if ( this.timeStarted < a.timeStarted )
            return -1;
        else {
             if ( this.timeEnded > a.timeEnded )
                 return 1;
             else
                 return -1;
        }
 }

Bu sana kaba bir fikir vermeli. Bu bittiğinde, Collections.sort()listeden arayabilirsiniz .


4

Java8'den bu yana, bu Comparatorve kombinasyonu kullanılarak daha temiz yapılabilir.Lambda expressions

Örneğin:

class Student{

    private String name;
    private List<Score> scores;

    // +accessor methods
}

class Score {

    private int grade;
    // +accessor methods
}

    Collections.sort(student.getScores(), Comparator.comparing(Score::getGrade);

2

Guava'nın Karşılaştırma Zinciri :

Collections.sort(list, new Comparator<ActiveAlarm>(){
            @Override
            public int compare(ActiveAlarm a1, ActiveAlarm a2) {
                 return ComparisonChain.start()
                       .compare(a1.timestarted, a2.timestarted)
                       //...
                       .compare(a1.timeEnded, a1.timeEnded).result();
            }});


1

Java'da statik Collections.sortyöntemi kullanmanız gerekir . Aşağıda, önce başlayıp sonra sona göre sıralanmış CompanyRole nesnelerinin listesi için bir örnek verilmiştir. Kendi nesnenize kolayca uyum sağlayabilirsiniz.

private static void order(List<TextComponent> roles) {

    Collections.sort(roles, new Comparator() {
        @Override
        public int compare(Object o1, Object o2) {
            int x1 = ((CompanyRole) o1).getBegin();
            int x2 = ((CompanyRole) o2).getBegin();

            if (x1 != x2) {
                return x1 - x2;
            } else {
                int y1 = ((CompanyRole) o1).getEnd();
                int y2 = ((CompanyRole) o2).getEnd();
                return y2 - y1;
            }
        }
    });
}

0

Collections.sort () öğesini çağırabilir ve nesnenin farklı özelliklerini karşılaştırmak için yazmanız gereken bir Karşılaştırıcıyı iletebilirsiniz.


0

Bahsedildiği gibi sıralayabilirsiniz:

  • Nesnenizi uygulamak Comparable
  • Ya da bir geçiş ComparatoriçinCollections.sort

İkisini de yaparsanız, yok Comparablesayılacak ve Comparatorkullanılacaktır. Bu, değer nesnelerinin, Comparabledeğer nesneniz için en makul sıralama olan kendi mantığına sahip olmasına yardımcı olurken, her bir kullanım durumunun kendi uygulaması vardır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.