You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将二维数组元素作为Map的Key正确存入?

嘿,我发现你现在的写法会踩一个Java里的常见坑——用数组作为HashMap的Key时,默认的行为和你预期的不一样!

原因很简单:Java中的数组是对象,但它继承的是Object类的equals()和hashCode()方法,这两个方法是基于对象引用来判断的,而不是数组里的内容。也就是说,哪怕两个数组的元素完全相同,只要它们是不同的数组对象(比如你代码里的points[0]和一个新创建的int[]{1,2}),HashMap就会把它们当成完全不同的Key,根本不会认为是同一个键。

那该怎么解决呢?给你三种靠谱的方案,按需选择:


方案一:用List<Integer>代替int[]作为Key

List接口的实现类(比如ArrayList)已经帮你重写了equals()和hashCode(),是基于集合内容来判断的,完美符合你的需求。写法也很简单:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;

public class TrySome {
    static int[][] points = {{1,2}, {1,1}, {5,7}};
    
    public static void some() {
        HashMap<List<Integer>, Integer> map = new HashMap<>();
        for(int[] point : points) {
            List<Integer> key = new ArrayList<>();
            key.add(point[0]);
            key.add(point[1]);
            map.put(key, 1);
        }
        
        for(Entry<List<Integer>, Integer> entry : map.entrySet()) {
            System.out.println(entry.getKey() + " : " + entry.getValue());
        }
    }
    
    public static void main(String[] args) {
        some();
    }
}

这个方案的优点是零额外代码,直接用JDK自带的类就能搞定,适合快速实现。缺点是如果数组元素很多,包装成List的性能会稍逊于自定义类。


方案二:自定义一个包装类,重写equals()和hashCode()

如果你追求更好的性能,或者想让代码语义更清晰(比如明确这是一个坐标点),可以自己写一个简单的类来包装数组元素:

import java.util.HashMap;
import java.util.Map.Entry;

class Point {
    private final int x;
    private final int y;
    
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
    
    // 重写equals:只有x和y都相等时,才认为两个Point对象相等
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Point point = (Point) o;
        return x == point.x && y == point.y;
    }
    
    // 重写hashCode:基于x和y计算哈希值,保证equals相等的对象hashCode也相等
    @Override
    public int hashCode() {
        int result = x;
        result = 31 * result + y; // 31是常用的质数,能减少哈希冲突
        return result;
    }
    
    // 重写toString,方便打印输出
    @Override
    public String toString() {
        return "[" + x + ", " + y + "]";
    }
}

public class TrySome {
    static int[][] points = {{1,2}, {1,1}, {5,7}};
    
    public static void some() {
        HashMap<Point, Integer> map = new HashMap<>();
        for(int[] point : points) {
            Point key = new Point(point[0], point[1]);
            map.put(key, 1);
        }
        
        for(Entry<Point, Integer> entry : map.entrySet()) {
            System.out.println(entry.getKey() + " : " + entry.getValue());
        }
    }
    
    public static void main(String[] args) {
        some();
    }
}

这个方案的优势是性能更高,而且代码可读性强,别人一看就知道这是一个坐标点。如果你的数组是更高维度的,只需要扩展这个类的属性就行。


方案三:借助第三方工具类(可选)

如果你已经在项目中使用了Apache Commons Lang库,可以直接用ArrayUtils.hashCode(int[])和ArrayUtils.isEquals(int[], int[])来辅助,但需要自己包装一下。不过因为要引入第三方依赖,一般不是首选,除非项目里已经有了。


最后再强调一下你原来代码的问题:假设你现在用map.get(new int[]{1,2}),会返回null,因为这个新数组和points[0]是不同的对象,HashMap认不出来。而用上面的方案一或二,map.get(List.of(1,2))或者map.get(new Point(1,2))就能正确返回1了。

内容的提问来源于stack exchange,提问作者user7748519

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:36:19