일부 속성별로 개체 목록을 정렬하는 방법
간단한 수업이 있습니다
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)
);
The above code will sort the list first by timeStarted
, and then by timeEnded
(for those records that have the same timeStarted
).
One last note: It is easy to compare 'long' or 'int' primitives, you can just subtract one from the other. If you are comparing objects ('Long' or 'String'), I suggest you use their built-in comparison. Example:
Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.name.compareTo(a2.name) );
EDIT: Thanks to Lukas Eder for pointing me to .thenComparing()
function.
We can sort the list in one of two ways:
1. Using Comparator : When required to use the sort logic in multiple places If you want to use the sorting logic in a single place, then you can write an anonymous inner class as follows, or else extract the comparator and use it in multiple places
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;
}
});
We can have null check for the properties, if we could have used 'Long' instead of 'long'.
2. Using Comparable(natural ordering): If sort algorithm always stick to one property: write a class that implements 'Comparable' and override 'compareTo' method as defined below
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;
}
}
call sort method to sort based on natural ordering
Collections.sort(list);
In java8+ this can be written in single line as follows,
collectionObjec.sort(comparator_lamda) or comparator.comparing(CollectionType::getterOfProperty)
code :
ListOfActiveAlarmObj.sort((a,b->a.getTimeStarted().compareTo(b.getTimeStarted())))
or
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;
}
}
That should give you a rough idea. Once that's done, you can call Collections.sort()
on the list.
Since Java8 this can be done even cleaner using a combination of Comparator
and Lambda expressions
For Example:
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);
Guava's ComparisonChain:
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();
}});
In java you need to use the static Collections.sort
method. Here is an example for a list of CompanyRole objects, sorted first by begin and then by end. You can easily adapt for your own object.
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;
}
}
});
}
You can call Collections.sort() and pass in a Comparator which you need to write to compare different properties of the object.
You can use Collections.sort
and pass your own Comparator<ActiveAlarm>
As mentioned you can sort by:
- Making your object implement
Comparable
- Or pass a
Comparator
toCollections.sort
If you do both, the Comparable
will be ignored and Comparator
will be used. This helps that the value objects has their own logical Comparable
which is most reasonable sort for your value object, while each individual use case has its own implementation.
참고URL : https://stackoverflow.com/questions/5805602/how-to-sort-list-of-objects-by-some-property
'development' 카테고리의 다른 글
부트 스트랩에서 탭을 비활성화 할 수 있습니까? (0) | 2020.07.01 |
---|---|
FileProvider 충돌-null 문자열에서 XmlResourceParser를 호출하려고 시도합니다. (0) | 2020.07.01 |
JSON 문자열을 JSON 객체로 변환 C # (0) | 2020.07.01 |
Angular 2에서 싱글 톤 서비스를 어떻게 만듭니 까? (0) | 2020.07.01 |
Angular2 ngSwitch 문에서 typescript 열거 형 값을 사용하는 방법 (0) | 2020.07.01 |