
java 中 `hashmap` 默认使用对象的 `equals()` 和 `hashcode()` 判断键是否相等;而 `int[]` 是引用类型,其 `equals()` 比较的是内存地址而非元素内容,因此即使两个 `int[]` 内容完全相同,`hashmap` 也视为不同键,导致 `get()` 返回 `null`。
根本原因在于:Java 数组没有重写 Object.equals() 方法。默认继承自 Object 的 equals() 实现仅做引用比较(即 ==),不进行内容比对。这意味着:
int[] a = {1, 2, 3};
int[] b = {1, 2, 3};
System.out.println(a.equals(b)); // false —— 即使内容相同,也是不同对象
System.out.println(Arrays.equals(a, b)); // true —— 正确的内容比较方式同理,hashCode() 也未重写,a.hashCode() 与 b.hashCode() 极大概率不同(取决于内存地址),这进一步破坏了 HashMap 的哈希桶定位逻辑——即使 equals() 偶然返回 true,哈希冲突或桶错位仍会导致查找失败。
✅ 正确解决方案
方案 1:改用不可变、内容可比的键类型(推荐)
避免使用数组作键,改用 List
// 使用 List(自动支持内容 equals/hashCode) Map, int[]> coloursMap = new HashMap<>(); List
coord = Arrays.asList(i, j, k); coloursMap.put(coord, new int[]{1, 2, 3}); // 查找时同样构造相同 List public int[] getColourFromHashInts(int i, int j, int k) { return coloursMap.get(Arrays.asList(i, j, k)); }
✅ 优势:简洁、线程安全(若用 Collections.unmodifiableList)、语义清晰。
方案 2:使用 Arrays.hashCode() + Arrays.equals() 自定义包装类
若必须用原始数组,可封装为 Key 类:
public static final class CoordKey {
private final int[] coords;
public CoordKey(int i, int j, int k) {
this.coords = new int[]{i, j, k};
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CoordKey coordKey = (CoordKey) o;
return Arrays.equals(coords, coordKey.coords);
}
@Override
public int hashCode() {
return Arrays.hashCode(coords);
}
}
// 使用:
Map map = new HashMap<>();
map.put(new CoordKey(i, j, k), cols); ❌ 错误尝试(不推荐)
- Arrays.asList(new int[]{i,j,k}) → 返回 List
(单元素列表),非 List ,无效; - new Integer[]{i,j,k} → 虽可比,但装箱开销大,且 Integer[] 同样不重写 equals()(需用 Arrays.equals)。
⚠️ 注意事项
- HashMap 键对象在插入后不应修改其影响 hashCode()/equals() 的状态(对数组而言即不能修改元素值);
- 若键需序列化或跨线程共享,优先选择不可变类型(如 List.of(i,j,k) Java 9+);
- 性能敏感场景下,可预计算哈希码(如 i * 31^2 + j * 31 + k)实现轻量 CoordKey。
总之,永远不要直接用原始数组(int[], String[] 等)作为 HashMap 的键——这是 Java 集合使用的经典陷阱之一。










