Problem
I have a Map<Date, Foo>, and a list of objects from the database with an effectiveDate property, and I want to check to see if the Date keys in my map are equal to any of the effectiveDates in the database - if so, do stuff with Foo.
The code looks something like this:
for (Bar bar : databaseBars) {
Foo foo = new Foo();
if (dateMap.containsKey(bar.getEffectiveDate()) {
foo = dateMap.get(bar.getEffectiveDate());
}
// do stuff with foo and bar
}
However, the dateMap.containsKey call always returns false, even though I'm sure it's sometimes there.
Investigation
As a sanity check, I've printed out the long values of the dates, as well as the results of an equals() call and a compareTo() call:
for (Date keyDate : dateMap.keySet()) {
if (keyDate == null) {
continue; // make things simpler for now
}
Date effDate = bar.getEffectiveDate();
String template = "keyDate: %d; effDate: %d; equals: %b; compareTo: %d\n";
System.out.printf(template, keyDate.getTime(), effDate.getTime(), effDate.equals(keyDate), effDate.compareTo(keyDate));
}
The results:
keyDate: 1388534400000; effDate: 1388534400000; equals: false; compareTo: 0
keyDate: 1420070400000; effDate: 1388534400000; equals: false; compareTo: -1
keyDate: 1388534400000; effDate: 1420070400000; equals: false; compareTo: 1
keyDate: 1420070400000; effDate: 1420070400000; equals: false; compareTo: 0
keyDate: 1388534400000; effDate: 1388534400000; equals: false; compareTo: 0
keyDate: 1420070400000; effDate: 1388534400000; equals: false; compareTo: -1
keyDate: 1388534400000; effDate: 1420070400000; equals: false; compareTo: 1
keyDate: 1420070400000; effDate: 1420070400000; equals: false; compareTo: 0
keyDate: 1388534400000; effDate: 1388534400000; equals: false; compareTo: 0
keyDate: 1420070400000; effDate: 1388534400000; equals: false; compareTo: -1
keyDate: 1388534400000; effDate: 1420070400000; equals: false; compareTo: 1
keyDate: 1420070400000; effDate: 1420070400000; equals: false; compareTo: 0
Question
1) Shouldn't equals and compareTo agree? (I assume the implementation of java.util.Date at least should try to follow the recommendation of java.lang.Comparable).
2) The Date#equals doc says this:
Thus, two Date objects are equal if and only if the getTime method returns the same long value for both.
...Looks like the getTime method returns the same long value for both of these dates, yet equal returns false. Any ideas why this might be happening? I've searched high and low, but I haven't found anyone describing the same problem.
P.S. I'm stuck using java.util.Date. Please don't just recommend JodaTime.
P.P.S. I realize I could just change the structure of this code and probably get it working. But this should work, and I don't want to just work around it, unless it's a known issue or something. It just seems wrong.