我有一个Map<Date, Foo>
,以及一个带有effectiveDate
属性的数据库对象列表,我想检查一下Date
我的映射中的键是否等于effectiveDate
数据库中的任何s-
如果是,请用填充Foo
。
代码看起来像这样:
for (Bar bar : databaseBars) {
Foo foo = new Foo();
if (dateMap.containsKey(bar.getEffectiveDate()) {
foo = dateMap.get(bar.getEffectiveDate());
}
// do stuff with foo and bar
}
但是,dateMap.containsKey
即使我确定有时会在该电话中,该电话始终会返回false。
作为健全性检查,我打印了日期的长值以及equals()
呼叫和compareTo()
呼叫的结果:
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));
}
结果:
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
1)不应该equals
和compareTo
同意吗?(我假设java.util.Date
至少应执行的建议java.lang.Comparable
)。
2)该Date#equals
医生说这个:
因此,当且仅当getTime方法返回两个相同的long值时,两个Date对象才相等。
…看起来该getTime
方法对于这两个日期都返回相同的long值,但equal
返回false。任何想法为什么会发生这种情况?我搜索过很多,但没有找到任何描述相同问题的人。
PS我被困住了java.util.Date
。请不要只是推荐JodaTime。
PPS我意识到我可以更改此代码的结构并可能使其工作。但这应该可以工作,除非有已知问题或其他原因,否则我不想仅仅解决它。似乎是 错误的 。
正如Mureinik所暗示和SotiriosDelimanolis更加具体指出的那样,这里的问题在于实现java.util.Date
。
java.util.Date
在java.sql
包中被3个类扩展,所有这些类似乎都做类似的事情,并且它们在java中的区别根本不清楚(似乎它们存在的原因仅仅是使Java类更准确地与SQL数据类型对齐)-有关它们之间差异的更多信息,请查看此非常详细的答案。
现在,在看似严重的设计缺陷中,有人决定对它进行equals()
不对称处理java.sql.Timestamp
-也就是说,timestamp.equals(date)
即使date.equals(timestamp)
返回true ,也可能返回false
。好想法。
我写了几行代码,看看哪些java.sql
类展示了这个荒谬的特性-显然只是Timestamp
。这段代码:
java.util.Date utilDate = new java.util.Date();
java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());
System.out.println("sqlDate equals utilDate:\t" + sqlDate.equals(utilDate));
System.out.println("utilDate equals sqlDate:\t" + utilDate.equals(sqlDate));
java.sql.Time time = new java.sql.Time(utilDate.getTime());
System.out.println("time equals utilDate:\t\t" + time.equals(utilDate));
System.out.println("utilDate equals time:\t\t" + utilDate.equals(time));
java.sql.Timestamp timestamp = new java.sql.Timestamp(utilDate.getTime());
System.out.println("timestamp equals utilDate:\t" + timestamp.equals(utilDate));
System.out.println("utilDate equals timestamp:\t" + utilDate.equals(timestamp));
产生此:
sqlDate equals utilDate: true
utilDate equals sqlDate: true
time equals utilDate: true
utilDate equals time: true
timestamp equals utilDate: false
utilDate equals timestamp: true
由于在(而不是)的实现中java.util.HashMap
使用parameter.equals(key)
了该containsKey()
key.equals(parameter)
结果,因此在给定的情况下会显示出一个奇怪的结果。
那么,如何解决这个问题?
1)使用Long
的地图键,而不是一个Date
(如Mureinik说明)
-自从java.util.Date
和java.util.Timestamp
来自返回相同的值getTime()
,它不应该不管你使用的实施,关键将是相同的。这种方法看起来确实是最简单的。
2)在地图中使用日期对象之前,先对其进行标准化。这种方法需要一点点工作,但对我来说似乎更可取,因为它更清楚地图是什么-
一堆Foo
存储在一个时刻。这是我最终通过以下方法使用的方法:
public Date getStandardizedDate(Date date) {
return new Date(date.getTime());
}
这需要一个额外的方法调用(这在当时是一种荒谬的调用),但是对我而言,涉及的代码的更高可读性Map<Date,Foo>
是值得的。
我正在使用spring Roo并希望访问Controller类中的一个bean,该类在ApplicationContext.xml中具有以下配置: 配置类本身是: 在我的Controller中,我认为一个简单的Autowired注释应该可以完成这项工作 在启动过程中,spring在setSkipWeeks方法中打印消息。不幸的是,每当我在控制器中调用config.getSkipWeeks()时,它
当我运行以下程序时,它只打印 然而,从Java 8的equalsIgnoreCase文档中我们发现: 如果以下至少一项为真,则两个字符c1和c2被视为相同的忽略情况: •对每个字符应用java.lang.character.ToUpperCase(char)方法会产生相同的结果 所以我的问题是为什么这个程序不打印 在这两种操作中,都使用了大写字符。
我试图使用来传输我根据前面的问题设置的自定义标头。 我在文件中读到... 我的属性包括:
我正在和selenium一起工作,刮一些数据。 有一个按钮在页面上,我正在点击说“Custom_Cols”。这个按钮为我打开了一个窗口,我可以在那里选择我的列。 我的问题是为什么新窗口上的元素不可见,即使我正在等待元素的可见。补充一下,我已经尝试增加延迟时间,但我还是会偶尔出现这个错误。 我的密码在这里
我正在使用Grails 2.0.1中的springsecurity插件。我的角色层次结构和其他s2属性如下所示。