为何相同值的java.sql.Date返回不同hashCode,用作HashMap键查询为空?
问题原因
java.sql.Date的toString()方法只会输出年-月-日部分,但它本质继承自java.util.Date,底层存储的是精确到毫秒的时间戳:
- hashCode计算完全基于底层的完整毫秒时间戳生成
- equals判断也同样基于完整毫秒时间戳对比
你遇到的两个打印日期相同的对象,实际内部存储的毫秒时间戳存在差异,只是时分秒毫秒部分被toString()隐藏了,所以hashCode不同,作为HashMap的key自然无法匹配到对应值。
多数情况该问题是JDBC驱动读取DATE类型字段时未自动清空时分秒、或者业务代码构造java.sql.Date时未处理时分秒导致的。
解决方法
- 方案1:统一对
java.sql.Date做时分秒毫秒置零处理,存和取都用处理后的对象作为key
public static java.sql.Date truncateSqlDate(java.sql.Date date) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); // 清空时分秒毫秒 calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); return new java.sql.Date(calendar.getTimeInMillis()); } // 存入时处理 map.put(truncateSqlDate(resultObj.getTmsTrxSqlDate()), yourValue); // 查询时也做相同处理 map.get(truncateSqlDate(trxUniqueIdObj.getTrxDate()));
- 方案2:转成固定格式的字符串作为key,字符串的hashCode和equals都基于文本内容,不会出现匹配问题
// Java 8及以上可用DateTimeFormatter,线程安全 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); // 存入时转字符串 String dateKey = resultObj.getTmsTrxSqlDate().toLocalDate().format(formatter); map.put(dateKey, yourValue); // 查询时转相同格式字符串 String queryKey = trxUniqueIdObj.getTrxDate().toLocalDate().format(formatter); map.get(queryKey);
- 方案3(推荐,Java 8及以上):直接转成
LocalDate作为key,LocalDate本身只存储年月日属性,没有时分秒,hashCode和equals都基于日期值计算,完全适配该场景
// 存入时转LocalDate LocalDate dateKey = resultObj.getTmsTrxSqlDate().toLocalDate(); map.put(dateKey, yourValue); // 查询时也转LocalDate LocalDate queryKey = trxUniqueIdObj.getTrxDate().toLocalDate(); map.get(queryKey);
内容的提问来源于stack exchange,提问作者user630209
相关产品推荐
相关产品推荐

