Home / Java Patterns and Pitfalls     frequal.com

Sorting With Longs -- Java Collections and Lists

Recently I was sorting lists of files by their modification date. The date was stored as longs, so in the Comparator I subtracted the second file's modified value from the first. Since the compare() method requires an int return value, I then cast to an int. I think when I first did it a little voice in my head was saying 'lack of precision', but the other little voice in my head said 'these values will all be pretty close'.

The problem

It turns out the modification dates were sometimes years apart, enough to make the millisecond-based modification dates different by more than the precision of an integer. When a long value that exceeds the capacity of an int is cast to an int, it doesn't throw an exception, but the conversion is not useful, sometimes drastically changing the sign or magnitude of the original value. In my case, comparisons between files whose modification times were more than about 25 days apart produced sometimes-incorrect values from compare(), resulting in incorrect sorting.

The solution

I used Long.signum() to determine whether the difference was negative, positive, or zero. Then when cast to an int it was guaranteed to never be truncated.
      public int compare(Item o1, Item o2) {
        return (int) (Long.signum(o2.getModified() - o1.getModified()));
      }
In Java 8+, Comparator.comparingLong() provides similar functionality.
Last modified on 10 Jul 2021 by AO

Copyright © 2024 Andrew Oliver