前言

首先先预设一个场景吧,假设我想在二位随机数组中取出特定数字第一次出现的位置,显然找到这个数字后就应该跳出两层循环,但单纯的break是做不到的,那么便有了这篇文章。

//下面的例子用到的数组,其中要找的数字是3
public static final int[][] NUMBER =
{
    {26, 52, 99, 65, 82, 33, 66, 56, 70, 95},
    {66, 18, 3, 0, 99, 84, 72, 88, 43, 51},
    {8, 54, 25, 68, 36, 45, 86, 68, 81, 65},
    {70, 22, 24, 60, 35, 85, 89, 26, 54, 77},
    {28, 29, 34, 27, 94, 43, 98, 89, 46, 98},
    {80, 37, 12, 54, 47, 19, 40, 88, 72, 68},
    {0, 31, 45, 46, 83, 67, 94, 11, 95, 44},
    {47, 95, 24, 56, 26, 81, 40, 89, 62, 2},
    {22, 2, 92, 66, 71, 33, 43, 47, 27, 38},
    {84, 9, 46, 3, 76, 19, 14, 34, 13, 80}
};
//也可以自己生成一个随机数组,为了在代码中复用把按照数组格式它打印出来
public static void main(String[] args) {
    int[][] number = new int[10][10];
    for(int i = 0;i < 10;i++){
        for (int j = 0; j < 10; j++) {
            number[i][j] = (int)(Math.random()*100);
        }
    }
    System.out.println(
            Arrays.deepToString(number)
                    .replace('[','{')
                    .replace(']','}')
                    .replace("},","},\n")
    );

}

正文

在循环前加标签,break时加上标签名
public static void main(String[] args) {
    StringBuffer index = new StringBuffer();
    int number = 3;
    //加入标签
    endFor:
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 10; j++) {
            if(Tool.NUMBER[i][j] == number){
                index.append("i=").append(i).append(",j=").append(j);
                //跳出外层循环
                break endFor;
            }
        }
    }
    System.out.println(index);
}

这种方式是最灵活好用的,可以自由选择跳出循环的层数,可读性也不错。
不过大部分情况下只有两层循环嵌套,没必要使用这种方法。
此外continue也有类似的用法。

使用一个标志位
public static void main(String[] args) {
    StringBuffer index = new StringBuffer();
    int number = 3;
    //加入标志位
    boolean isFind = false;
    //再循环条件中使用标志位
    for (int i = 0; i < 10 && !isFind; i++) {
        for (int j = 0; j < 10; j++) {
            if(Tool.NUMBER[i][j] == number){
                index.append("i=").append(i).append(",j=").append(j);
                //满足要求时改变标志位
                isFind = true;
                break;
            }
        }
    }
    System.out.println(index);
}

同样逻辑清晰简单易懂,问题是在遇到多层循环的时候就变得很麻烦,不过在只有两层循环的时候很好用。

直接改变控制外层for循环的变量
public static void main(String[] args) {
    StringBuffer index = new StringBuffer();
    int number = 3;
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 10; j++) {
            if(Tool.NUMBER[i][j] == number){
                index.append("i=").append(i).append(",j=").append(j);
                //改变控制外层循环的变量值
                i = 11;
                break;
            }
        }
    }
    System.out.println(index);
}

可读性就不如上一个方法,但是优缺点和上一个方法基本是相同的。
不过必须要注意的是,改变控制外层循环的变量值尽量放在break前一行,以免取到错误的值。

写匿名函数跳出
public static void main(String[] args) {
    StringBuffer index = new StringBuffer();
    int number = 3;
    //写一个匿名函数
    FindNumber findNumber = (theNumber) ->
    {
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 10; j++) {
                if(Tool.NUMBER[i][j] == theNumber){
                    index.append("i=").append(i).append(",j=").append(j);
                    //满足要求时跳出匿名函数
                    return;
                }
            }
        }
        return;
    };
    //运行匿名函数
    findNumber.TheFunction(number);
    System.out.println(index);
}
interface FindNumber {
    void TheFunction(int a);
}

可读性显然没那么强而且写起来也不大方便的方法,而且基本上也只能跳出最外层循环。
完全可以用下一种方法代替。

捕获自定义异常
public static void main(String[] args) {
    StringBuffer index = new StringBuffer();
    int number = 3;
    try {
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 10; j++) {
                if(Tool.NUMBER[i][j] == number){
                    index.append("i=").append(i).append(",j=").append(j);
                    //满足要求时抛出自定义异常
                    throw new Exception("EndFor");
                }
            }
        }
    }catch (Exception EndFor){
        //捕获自定义异常
    }finally {
        System.out.println(index);
    }
}

可读性还可以,如果有大量不同层循环需要跳出到最外层或者多个顺序操作达成条件后就不必执行后续操作就可以使用这种方法。