Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort by date descending comparator not working as expected

Trying to make sense of the following output:

public class CommunicationComparator implements Comparator<Communication> {
    @Override
    public int compare(Communication comm1, Communication comm2) {
        long t1 = comm1.getDate().getTime();
        long t2 = comm2.getDate().getTime();
        return (int) (t2 - t1);
    }
}

The method getDate() returns a java.sql.Timestamp.

Here is the output before the sort:

for (Communication n : retVal) {
    System.out.println(n.getDate().toString());
}

2012-10-03 10:02:02.0
2012-10-07 03:02:01.0
2012-10-08 13:02:02.0
2012-10-09 03:02:00.0
2012-11-26 10:02:05.0
2012-11-28 11:28:11.0
2012-12-03 12:03:01.0
2012-12-06 15:03:01.0
2012-12-13 14:03:00.0
2012-12-28 11:03:00.0
2012-12-28 13:49:21.0

And after:

Collections.sort(retVal, new CommunicationsComparator());

2012-12-13 14:03:00.0
2012-12-06 15:03:01.0
2012-12-03 12:03:01.0
2012-11-28 11:28:11.0
2012-10-09 03:02:00.0
2012-10-08 13:02:02.0
2012-11-26 10:02:05.0
2012-10-07 03:02:01.0
2012-10-03 10:02:02.0
2012-12-28 13:49:21.0
2012-12-28 11:03:00.0

Any ideas why the bottom two objects might not be sorted correctly? I am using the MySQL JDBC implementation of this Timestamp.

like image 636
maple_shaft Avatar asked Jan 02 '13 16:01

maple_shaft


2 Answers

The difference between the last 2 dates and earlier dates will overflow integer.

Perhaps a better solution would be to compare the values, rather than subtract them.

    long t1 = comm1.getDate().getTime();
    long t2 = comm2.getDate().getTime();
    if(t2 > t1)
            return 1;
    else if(t1 > t2)
            return -1;
    else
            return 0;
like image 147
James McMinn Avatar answered Sep 30 '22 19:09

James McMinn


If the difference is bigger than about 25 days, an overflow occurs. (An int cannot represent a bigger time difference in milliseconds than about 25 days). This will make the comparison incorrect.

This can be solved by changing the return statement into:

return Long.signum(t2 - t1);
like image 35
gogognome Avatar answered Sep 30 '22 20:09

gogognome