Java二维矩阵行索引替换:用MyLocalDate哈希值替代0-365索引
解决Java二维矩阵用MyLocalDate索引的问题
直接使用MyLocalDate.hashCode()作为数组行索引是不可行的,原因有两个:
- 默认的
hashCode()返回值范围是-2^31到2^31-1,远超出你数组的0-365行范围,会直接抛出ArrayIndexOutOfBoundsException。 - 不同的
MyLocalDate对象可能产生相同的哈希值(哈希冲突),导致不同日期的数据被覆盖。
下面提供两种可靠的实现方案,让你可以像预期那样访问矩阵数据:
方案一:自定义索引方法(推荐)
不修改hashCode()的原有逻辑(避免影响哈希集合的正常使用),给MyLocalDate添加一个专门的索引转换方法,返回该日期在当年的0-365索引值:
public class MyLocalDate { // 假设你的类已有year、month、day等字段 private int year; private int month; private int day; // 计算该日期在当年的天数(1-366),可以借助Java 8+的LocalDate实现 private int getDayOfYear() { return java.time.LocalDate.of(year, month, day).getDayOfYear(); } // 转换为数组的行索引(0-365) public int toMatrixIndex() { return getDayOfYear() - 1; } // 保留原有的equals和hashCode,用于其他哈希场景 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; MyLocalDate that = (MyLocalDate) o; return year == that.year && month == that.month && day == that.day; } @Override public int hashCode() { // 保持默认或原有实现,比如: return Objects.hash(year, month, day); } }
使用方式非常简单,和你预期的写法几乎一致:
int[][] dataset = new int[366][27]; MyLocalDate targetDate = new MyLocalDate(2024, 5, 15); // 示例日期 int data = dataset[targetDate.toMatrixIndex()][10];
额外优化:添加年份校验
如果你的矩阵只存储某一年的数据,可以给索引方法加年份校验,避免错误日期写入:
public int toMatrixIndex(int targetYear) { if (this.year != targetYear) { throw new IllegalArgumentException("日期不属于目标年份:" + targetYear); } return getDayOfYear() - 1; }
使用时指定目标年份:
int targetYear = 2024; int data = dataset[targetDate.toMatrixIndex(targetYear)][10];
方案二:重写hashCode()(谨慎使用)
如果你确定不会在其他哈希集合(如HashMap、HashSet)中使用MyLocalDate,可以重写hashCode()让它直接返回矩阵行索引:
public class MyLocalDate { private int year; private int month; private int day; private int getDayOfYear() { return java.time.LocalDate.of(year, month, day).getDayOfYear(); } @Override public int hashCode() { // 返回0-365的索引值 return getDayOfYear() - 1; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; MyLocalDate that = (MyLocalDate) o; return year == that.year && month == that.month && day == that.day; } }
这样就可以完全按照你想要的方式访问数据:
int[][] dataset = new int[366][27]; int data = dataset[targetDate.hashCode()][10];
⚠️ 注意:这种方式会破坏hashCode()的通用约定——不同年份的同一天(比如2023-01-01和2024-01-01)会有相同的hashCode,但equals返回false,如果把这些对象放入HashMap,会导致哈希冲突,降低集合性能。
内容的提问来源于stack exchange,提问作者Chayma Sakouhi
相关产品推荐
相关产品推荐

