Reputation: 514
Supposing that I have a list of Test as below:
public class Test {
public static enum Unit {
DAY, WEEK, MONTH, YEAR /* , DAY_TO_DAY */
}
private int value;
private Unit unit;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public Unit getUnit() {
return unit;
}
public void setUnit(Unit unit) {
this.unit = unit;
}
}
I will have a list of Test with the below values :
3 day, 5 month, 5 day, 6 year, 6 week, 12 week,
and our expection result as below :
3 day, 5 day, 6 week , 12 week, 5 month, 6 year
Currently, I create a code as below
Collections.sort(tests, new Comparator<Test >() {
@Override
public int compare(Test o1, Test o2) {
if(o1.getValue() > o2.getValue()) return 1;
if(o1.getValue() < o2.getValue()) return -1;
return 0;
}
However, it only sort by value and not by Unit. The result with the above implementation is :
3 day, 5 day, 5 month, 6 week , 6 year, 12 week.
Please tell me know the way to satisfy two conditions (Unit and values) in this case. Thanks.
Upvotes: 2
Views: 103
Reputation: 121702
Use TimeUnit
to replace your Unit
enum.
Your Term
class could therefore have a .toMillis()
method which is very simple:
public final long toMillis()
{
return timeUnit.toMillis(value);
}
You can then just Long.compare(o1.toMillis(), o2.toMillis())
in your Comparator
.
Other solutions:
Period
. It is nearly equivalent to that of Java 8's/threetenbp's.Upvotes: 1
Reputation: 1
Please use the compareto function as below:
public int compareTo(Object o) {
Test t1 = (Test)this;
Test t2 = (Test)o;
if(t1.getValue()*(t1.getUnit().getValue()+1) > t2.getValue()*(t2.getUnit().getValue()+1)) return 1;
if(t1.getValue()*(t1.getUnit().getValue()+1) < t2.getValue()*(t2.getUnit().getValue()+1)) return -1;
return 0;
}
and change the enum to
public static enum Unit {
DAY(1), WEEK(7), MONTH(31), YEAR(365) ;/* , DAY_TO_DAY */
private final int id;
Unit(int id) { this.id = id; }
public int getValue() { return id; }
}
Now you use the collection.sort(), and it will be sorted automatically
Upvotes: 0
Reputation: 31
You'll first have to check on the basis of Unit and then on the basis of Value in the overridden compareTo(). See here the implementation of sorting on the basis of lastname and then firstname:http://docs.oracle.com/javase/tutorial/collections/interfaces/order.html
Upvotes: 1
Reputation: 19201
If you simply want to compare according to your example the following code solves the problem:
Collections.sort(terms, new Comparator<Test>() {
@Override
public int compare(final Test o1, final Test o2) {
int unitCompare = o1.getUnit().compareTo(o2.getUnit());
if (unitCompare == 0) {
return o1.getValue() - o2.getValue();
}
return unitCompare;
}
});
However, this code does NOT factor in that months can have different length and the code does NOT factor in that 35 days is longer than a month.
In order to do that i suggest that the classes from the java.time
package (such as java.time.Period
) are used to make proper comparisons (a good trail to learn about this can be found here). If Java 8 is not an option Joda Time provides the same type of functionality.
Upvotes: 1
Reputation: 2766
If you really want to do it that way, assign your enums values like so: DAY(1), WEEK(7), MONTH(31), YEAR(365)
than multiply in your comperator Unit.getValue() * value
e.g. 4 MONTH gives you 31 * 4 = 124 is bigger than 100 DAY.
still you have the problem that teher are months with less than 31 days. recommend to convert to some common date units e.g. joda time.
Upvotes: 0
Reputation: 20520
You'll need to convert first into common format, and then compare. Since days are your smallest type, you should convert the two instances you're comparing into a number of days, and then compare based on that.
But you have some disambiguation to do first. How long is a month? Is it longer than 30 days, or shorter, or the same?
Upvotes: 5