Reputation: 35034
I am sorting my custom objects. Custom object contain state and timestamp. First I have to sort against state then timestamp. State having below values
Running, Waiting, Registering, Completed and Aborted
So state having value Running should come on top then Waiting and so on.
If I have to sort alphabetically then I can do easily via
state1.compareTo(state2)
But can I sort with this criteria. Please help me to write this logic.
EDIT
As you people suggested I took Enum
private enum TournamentState {
Running,
Waiting,
Registering,
Completed,
Aborted
}
And compare like below
int sort = EnumState.valueOf(status1).compareTo(EnumState.valueOf(status2));
if(sort != 0){
return sort;
}else{
return (int) (time1 - time2);
}
Thank you very much for your support.
Upvotes: 1
Views: 1488
Reputation: 45309
You can use composition of comparator functions:
Comparator<MyClass> comparator = Comparator.comparing(MyClass::getState)
.thenComparing(MyClass::getTimeStamp);
The last line may need to be changed accordingly, depending on the data type:
.thenComparingLong(MyClass::getTimeStamp); //if it's a long TS
Or even
.thenComparing((ts1, ts2) -> {
//custom comparison logic for time stamp values
return result;
});
Comparator.thenComparing
is documented with this comment:
Returns a lexicographic-order comparator with another comparator. If this Comparator considers two elements equal, i.e. compare(a, b) == 0, other is used to determine the order.
Note that MyClass.state
is assumed to be comparable in this case, such as being an enum, which is inherently comparable. If it's plain strings, then you may need custom logic there too, such as with:
final String order = "Running, Waiting, Registering, Completed and Aborted";
Comparator<MyClass> comparator =
Comparator.comparingInt(e -> order.indexOf(e.getState()))
.thenComparing(MyClass::getTimeStamp);
Upvotes: 4
Reputation: 4967
You can create a custom comparator for your State
class, like this :
public final class StateComparator implements Comparator<State>
{
private int getRank(final State s)
{
if (s.getValue().equals("Running"))
{
return 1;
} else if (s.getValue().equals("Waiting")) {
return 2;
} else if (s.getValue().equals("Registering")) {
return 3;
} else if (s.getValue().equals("Completed")) {
return 4;
} else if s.getValue().equals("Aborted") {
return 5;
} else {
return Integer.MAX_VALUE;
}
}
public int compare(final State s1, final State s3)
{
return getRank(s1) - getRank(S2);
}
}
Upvotes: 2
Reputation: 4537
You can create an enum like
public enum State {
RUNNING, WAITING, REGISTERING, COMPLETED, ABORTED
}
By default, these states will get an ordinal integer which will be according to the order you write them in the enum. And then use this State
as your state
in your object and the create comparator
Comparator<MyClass> comparator = Comparator.comparing(MyClass::getState)
.thenComparing(MyClass::getTimeStamp);
And then you can use the comparator to sort your collections
Upvotes: 0