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

HashSet.contains()使用问题排查:克鲁斯卡尔算法迷宫生成坐标检测

问题根源:Java数组的equals()坑

Yep,你完全说对了——问题就出在HashSet.contains()的使用上!核心原因是Java里数组的equals()方法默认比的是对象引用,不是数组里的内容。

你代码里每次都新建一个int[]{x, y - 2},哪怕这个新数组的元素和集合里某个数组完全一样,它也是个全新的对象,内存地址不一样,所以contains()永远返回false。

几种可行的修复方案

1. 用List<Integer>替代int[]

List的equals()方法是专门比较集合内容的,把坐标换成List就能让contains()正常工作:

// 把cells的类型改成 HashSet<HashSet<List<Integer>>>
for (HashSet<List<Integer>> h : cells) { 
    if (h.contains(Arrays.asList(x, y - 2))) { 
        set1 = h; 
    } 
}

直接用Arrays.asList()把坐标转成List就行,或者提前把所有坐标都存成ArrayList<Integer>。

2. 自定义坐标类并重写equals()和hashCode()

创建一个简单的Point类来封装坐标,自己控制相等性判断逻辑,这也是最规范的做法:

import java.util.Objects;

class Point {
    private final int x;
    private final int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @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;
    }

    @Override
    public int hashCode() {
        return Objects.hash(x, y);
    }
}

然后把集合里的元素都换成Point对象:

// cells的类型改为 HashSet<HashSet<Point>>
for (HashSet<Point> h : cells) { 
    if (h.contains(new Point(x, y - 2))) { 
        set1 = h; 
    } 
}

这种方式代码可读性更高,后续扩展也方便,比如要加坐标运算的话直接在Point类里加方法就行。

3. 手动遍历比较数组内容(不推荐)

如果不想改数据结构,也可以手动遍历集合里的每个数组,逐个元素比较:

for (HashSet<int[]> h : cells) { 
    for (int[] coord : h) {
        if (coord[0] == x && coord[1] == y - 2) {
            set1 = h;
            break;
        }
    }
}

但这种方式效率很低,尤其是当迷宫规模大的时候,不建议用。

额外小提示

对了,用Kruskal算法生成迷宫时,通常会用**并查集(Union-Find)**来管理连通分量,比嵌套HashSet的方式效率高太多了,还能避免这类对象相等性的问题。如果还没试过,强烈建议切换到并查集实现,会省心很多~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:50:33