Java 代码卡在循环中

Java 代码卡在循环中,java,Java,我制作了一个脚本,可以拍照,从左上角开始(在我的测试图像中是一个白色像素),然后像魔杖工具一样通过图像,选择颜色足够相似的像素 但即使循环次数超过图像中的像素数,脚本也不会完成执行 测试图像约为160K像素Tools.loadImage()是一种自行编写的方法。我在其他地方用过,很可能有用。下面不是我的全部代码,而是与问题相关的部分 static int[][][] image; public static void main(String[] args) { image = Tool

我制作了一个脚本,可以拍照,从左上角开始(在我的测试图像中是一个白色像素),然后像魔杖工具一样通过图像,选择颜色足够相似的像素

但即使循环次数超过图像中的像素数,脚本也不会完成执行

测试图像约为160K像素
Tools.loadImage()
是一种自行编写的方法。我在其他地方用过,很可能有用。下面不是我的全部代码,而是与问题相关的部分

static int[][][] image;

public static void main(String[] args) {
    image = Tools.loadImage(path1);

    int height = image.length;
    int width = image[0].length;
    int[][][] newImage = new int[height][width][4];

    ArrayList<Integer> toCheck = new ArrayList<Integer>();
    ArrayList<Integer> checked = new ArrayList<Integer>();

    int[] baseColor = image[0][0];
    toCheck.add(0);

    while (!toCheck.isEmpty()) {
        i++;
        int coords = toCheck.get(0);
        int x = coords % width;
        int y = coords / width;

        if (check(x, y, baseColor, 128)) {
            coords = y * width + x - 1;
            if (x > 0 && !(checked.contains(coords) || toCheck.contains(coords))) {
                toCheck.add(coords);
            }
            coords = y * width + x + 1;
            if (x < width - 1 && !(checked.contains(coords) || toCheck.contains(coords))) {
                toCheck.add(coords);
            }
            coords = (y - 1) * width + x;
            if (y > 0 && !(checked.contains(coords) || toCheck.contains(coords))) {
                toCheck.add(coords);
            }
            coords = (y + 1) * width + x;
            if (y < height - 1 && !(checked.contains(coords) || toCheck.contains(coords))) {
                toCheck.add(coords);
            }
        }

        checked.add(coords);
        toCheck.remove(0);
    }
}

static boolean check(int x, int y, int[] color, int threshold) {
    for (int i = 0; i < 3; i++) {
        if (Math.abs(image[y][x][i] - color[i]) > threshold) {
            return false;
        }
    }
    return true;
}
静态int[][]图像;
公共静态void main(字符串[]args){
image=Tools.loadImage(路径1);
int height=image.length;
int width=图像[0]。长度;
int[][]newImage=newint[height][width][4];
ArrayList toCheck=新建ArrayList();
选中ArrayList=新建ArrayList();
int[]baseColor=图像[0][0];
toCheck.add(0);
而(!toCheck.isEmpty()){
i++;
int coords=toCheck.get(0);
int x=坐标%width;
int y=坐标/宽度;
如果(勾选(x,y,基色,128)){
坐标=y*宽度+x-1;
如果(x>0&&!(选中.contains(coords)| | toCheck.contains(coords))){
toCheck.add(坐标);
}
坐标=y*宽度+x+1;
如果(x0&&!(选中.contains(coords)| | toCheck.contains(coords))){
toCheck.add(坐标);
}
坐标=(y+1)*宽度+x;
如果(y阈值){
返回false;
}
}
返回true;
}

如果你想指出一些明显的方法来加快这个循环,那也会很感激。

添加到复选框的位置不正确

while (!toCheck.isEmpty()) {
    i++;
    int coords = toCheck.get(0);
    checked.add(coords);        // important
    toCheck.remove(0);          // might as well do this here too
    int x = coords % width;
    int y = coords / width;

coords在循环中被重复覆盖,因此当前像素不会被添加,而是四个相邻像素中的最后一个。因此,某些条件稍后会失败,并且会添加一些错误的像素进行检查

您正在覆盖循环体中的
coords
,因此在每次迭代结束时,您标记了错误的像素。在弹出下一个点进行检查后,立即移动标记非常安全


Excel,考虑使用<代码> BITSET <代码>检查< /COD>(按@ JB NIZET的建议)和< <代码> ArrayDeque <代码> >代码>检查< <代码> .< /P> <代码>时间,这样您就可以使用HashSet了,这将是检查坐标输入的最佳方法。好的,哇,速度提高了一千倍,谢谢。不过仍然卡在这个循环中。@nhouser9,因为OP不想检查每个像素。@DawoodibnKareem一个位集将是一个更好的选择。请阅读(并遵循)这个感叹词,它总是一些简单的事情,每次检查代码时都会被忽略。非常感谢,我已经为此苦恼了几个小时。为什么不使用

位集
进行
检查
检查
?您需要能够从
检查
快速获得下一点
BitSet
确实有这样一种方法,但它需要对集合进行线性搜索,这可能是您想要避免的。
ArrayQue
将在固定时间内为其提供服务,同时将避免使用
ArrayList
对数组进行移位。好的,这很公平。