Sort by date descending comparator does not work as expected

Trying to understand the following conclusion:

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 getDate () method returns java.sql.Timestamp.

Here is the result before sorting:

 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 be sorted incorrectly? I am using the MySQL JDBC implementation of this timestamp.

+4
source share
4 answers

The difference between the last two dates and earlier dates will exceed an integer.

Perhaps the best 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; 
+16
source

If the difference exceeds 25 days, an overflow occurs. (An int cannot represent a large time difference in milliseconds than about 25 days). This will lead to an incorrect comparison.

This can be solved by changing the return statement to:

 return Long.signum(t2 - t1); 
+6
source

My first idea is an overflow problem. t1 and t2 are long s. Different ones may not fit into int.

I would check it out.

If the second level comparison is enough for you, you should try:

 return (int) ((t2 - t1)/1000); 

This does not guarantee that there will be no overflows. I would at least add a test.

I think the best answer is not mine. My favorites:

  if(t2 > t1) return 1; else if(t1 > t2) return -1; else return 0; 
+4
source

you can use

 return Long.compare(t2, t1); 

but you better compare dates.

 return comm2.getDate().compareTo(comm1.getDate()); 
+4
source

All Articles