[java] 일부 속성별로 개체 목록을 정렬하는 방법

간단한 수업이 있습니다

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

그리고 List<ActiveAlarm>죄수. 을 기준으로 오름차순으로 정렬 timeStarted한 다음 timeEnded? 아무도 도와 줄 수 있습니까? 나는 일반적인 알고리즘과 과부하 연산자 <를 사용하여 C ++에서 알고 있지만 Java를 처음 사용합니다.



답변

어느 만든다 ActiveAlarm구현 Comparable<ActiveAlarm>하거나 구현하는 Comparator<ActiveAlarm>별도의 클래스에서. 그런 다음 전화 :

Collections.sort(list);

또는

Collections.sort(list, comparator);

일반적으로, 구현하는 좋은 아이디어이다 Comparable<T>, 그렇지 않으면 … 하나의 “자연”정렬 순서가 있다면 (당신이 경우 일어날 특정 순서로 정렬 할 것이 아니라, 동등하게 쉽게 다른 일을 할 수 있습니다) 그것을 구현하는 것이 좋습니다 Comparator<T>. 이 특정 상황은 솔직히 말해서 어느 쪽이든 갈 수 있지만 더 유연한 옵션을 고수 할 것 입니다Comparator<T> .

편집 : 샘플 구현 :

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


답변

사용 Comparator

예를 들어 :

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부터는 람다 식을 사용하여 Comparator 인스턴스를 나타낼 수 있습니다.

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


답변

자바 8 이상 답변 (람다 식 사용)

Java 8에서는 Lambda 표현식이 도입되어 더욱 쉬워졌습니다! 모든 스캐 폴딩으로 Comparator () 객체를 만드는 대신 다음과 같이 단순화 할 수 있습니다. (객체를 예제로 사용)

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

또는 더 짧게 :

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

그 진술은 다음과 같습니다.

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

Lambda 표현식은 코드의 관련 부분 (메소드 서명 및 반환되는 항목) 만 입력하면된다고 생각하십시오.

질문의 또 다른 부분은 여러 필드와 비교하는 방법이었습니다. Lambda 표현식으로이를 수행하려면이 .thenComparing()함수를 사용 하여 두 비교를 하나로 결합 할 수 있습니다 .

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

위의 코드는 목록을 먼저 정렬 timeStarted한 다음 timeEnded(같은 레코드에 대해) 정렬합니다 timeStarted.

마지막 참고 사항 : ‘long’또는 ‘int’프리미티브를 쉽게 비교할 수 있습니다. 서로를 빼면됩니다. 객체 ( ‘Long’또는 ‘String’)를 비교하는 경우 기본 제공 비교를 사용하는 것이 좋습니다. 예:

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

편집 : .thenComparing()기능을 알려주는 Lukas Eder에게 감사드립니다 .


답변

다음 두 가지 방법 중 하나로 목록을 정렬 할 수 있습니다.

1. 비교기 사용 : 여러 장소에서 정렬 논리를 사용해야하는 경우 단일 장소에서 정렬 논리를 사용하려면 다음과 같이 익명 내부 클래스를 작성하거나 비교기를 추출하여 여러 위치에서 사용할 수 있습니다.

  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’대신 ‘Long’을 사용할 수 있다면 속성을 null 검사 할 수 있습니다.

2. Comparable (natural ordering) 사용 : 정렬 알고리즘이 항상 하나의 속성을 고수하는 경우 : ‘Comparable’을 구현하는 클래스를 작성하고 아래 정의 된대로 ‘compareTo’메소드를 재정의하십시오.

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

}

자연 순서에 따라 정렬하는 정렬 방법 호출

Collections.sort(list);


답변

java8 +에서는 다음과 같이 한 줄로 작성할 수 있습니다.

collectionObjec.sort(comparator_lamda) 또는 comparator.comparing(CollectionType::getterOfProperty)

암호:

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

또는

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


답변

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

그것은 당신에게 대략적인 아이디어를 줄 것입니다. 완료되면 Collections.sort()목록에서 전화 를 걸 수 있습니다 .


답변

Java8부터는 ComparatorLambda expressions

예를 들어 :

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