Reputation: 53836
In below code I'm attempting to custom sort by date descending a list of BasicDBObject.
The output printed is :
{ "year" : "2015" , "month" : "12" , "day" : "1" , "time" : "07:30:59"}
{ "year" : "2015" , "month" : "12" , "day" : "1" , "time" : "07:30:20"}
{ "year" : "2015" , "month" : "12" , "day" : "1" , "time" : "07:30:00"}
{ "year" : "2015" , "month" : "01" , "day" : "23" , "time" : "07:30:59"}
{ "year" : "2015" , "month" : "09" , "day" : "26" , "time" : "07:30:59"}
when it should be :
{ "year" : "2015" , "month" : "12" , "day" : "1" , "time" : "07:30:59"}
{ "year" : "2015" , "month" : "12" , "day" : "1" , "time" : "07:30:20"}
{ "year" : "2015" , "month" : "12" , "day" : "1" , "time" : "07:30:00"}
{ "year" : "2015" , "month" : "09" , "day" : "26" , "time" : "07:30:59"}
{ "year" : "2015" , "month" : "01" , "day" : "23" , "time" : "07:30:59"}
as September (09) occurs after January (01).
Is there an issue with sort compare method?
code :
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormatter;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
public class SortByDate
{
private void testSort()
{
List<DBObject> l = new ArrayList<DBObject>();
DBObject dbo = new BasicDBObject();
dbo.put("year", "2015");
dbo.put("month", "12");
dbo.put("day", "1");
dbo.put("time", "07:30:20");
l.add(dbo);
dbo = new BasicDBObject();
dbo.put("year", "2015");
dbo.put("month", "09");
dbo.put("day", "26");
dbo.put("time", "07:30:59");
l.add(dbo);
dbo = new BasicDBObject();
dbo.put("year", "2015");
dbo.put("month", "12");
dbo.put("day", "1");
dbo.put("time", "07:30:59");
l.add(dbo);
dbo = new BasicDBObject();
dbo.put("year", "2015");
dbo.put("month", "01");
dbo.put("day", "23");
dbo.put("time", "07:30:59");
l.add(dbo);
dbo = new BasicDBObject();
dbo.put("year", "2015");
dbo.put("month", "12");
dbo.put("day", "1");
dbo.put("time", "07:30:00");
l.add(dbo);
DateTimeFormatter dtf = org.joda.time.format.DateTimeFormat.forPattern("MM/dd/yyyy HH:mm:ss");
Collections.sort(l, new Comparator<DBObject>()
{
@Override
public int compare(final DBObject o1, final DBObject o2)
{
long m1 = dtf.parseMillis((String) o1.get("month")+"/"+(String) o1.get("day")+"/"+(String) o1.get("year")+" "+(String) o1.get("time"));
long m2 = dtf.parseMillis((String) o2.get("month")+"/"+(String) o2.get("day")+"/"+(String) o2.get("year")+" "+(String) o2.get("time"));
return (int)m2 - (int)m1;
}
});
for(DBObject d : l){
System.out.println(d.toString());
}
}
public static void main(String args[])
{
new SortByDate().testSort();
}
}
Upvotes: 0
Views: 265
Reputation: 1166
The problem is here:
return (int)m2 - (int)m1;
You convert long
millis to int
, but value is larger than Integer.MAX_VALUE
, so overflow happens and conversion returns wrong result (it can be negative, for example).
Correct conversion could be:
return (int)(m2 - m1);
But again, if date differs a lot, overflow still can happen. Correct and safe way to do what you need is to use Long.compare:
return Long.compare(m2, m1);
Upvotes: 1