我有一个这样的嵌套循环结构:
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
break; // Breaks out of the inner loop
}
}
}
现在我怎样才能摆脱两个循环?我看过类似的问题,但没有一个特别关注Java。我不能应用这些解决方案,因为大多数使用过。
我不想将内循环放在另一种方法中。
我不想重新运行循环。当我完成循环块的执行时。
答案 0 :(得分:2242)
和其他的回答者一样,我肯定更喜欢将循环放在一个不同的方法中,此时你可以返回完全停止迭代。这个答案只是说明了如何满足问题中的要求。
您可以使用带有外部循环标签的break
。例如:
public class Test {
public static void main(String[] args) {
outerloop:
for (int i=0; i < 5; i++) {
for (int j=0; j < 5; j++) {
if (i * j > 6) {
System.out.println("Breaking");
break outerloop;
}
System.out.println(i + " " + j);
}
}
System.out.println("Done");
}
}
打印:
0 0
0 1
0 2
0 3
0 4
1 0
1 1
1 2
1 3
1 4
2 0
2 1
2 2
2 3
Breaking
Done
答案 1 :(得分:381)
从技术上讲,正确的答案是标记外部循环。实际上,如果你想在内循环中的任何一点退出,那么你最好将代码外部化为一个方法(如果需要的话,静态方法),然后调用它。
这样可以获得可读性。
代码会变成这样:
private static String search(...)
{
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
return search;
}
}
}
return null;
}
匹配接受答案的示例:
public class Test {
public static void main(String[] args) {
loop();
System.out.println("Done");
}
public static void loop() {
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (i * j > 6) {
System.out.println("Breaking");
return;
}
System.out.println(i + " " + j);
}
}
}
}
答案 2 :(得分:203)
您可以在循环周围使用命名块:
search: {
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
break search;
}
}
}
}
答案 3 :(得分:122)
我从不使用标签。进入这似乎是一种不好的做法。这就是我要做的事情:
boolean finished = false;
for (int i = 0; i < 5 && !finished; i++) {
for (int j = 0; j < 5; j++) {
if (i * j > 6) {
finished = true;
break;
}
}
}
答案 4 :(得分:93)
您可以使用标签:
label1:
for (int i = 0;;) {
for (int g = 0;;) {
break label1;
}
}
答案 5 :(得分:34)
使用功能:
public void doSomething(List<Type> types, List<Type> types2){
for(Type t1 : types){
for (Type t : types2) {
if (some condition) {
// Do something and return...
return;
}
}
}
}
答案 6 :(得分:15)
您可以使用临时变量:
boolean outerBreak = false;
for (Type type : types) {
if(outerBreak) break;
for (Type t : types2) {
if (some condition) {
// Do something and break...
outerBreak = true;
break; // Breaks out of the inner loop
}
}
}
根据您的功能,您也可以从内循环退出/返回:
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
return;
}
}
}
答案 7 :(得分:11)
如果您不喜欢break
和goto
,则可以使用“传统”for循环代替for-in,并使用额外的中止条件:
int a, b;
bool abort = false;
for (a = 0; a < 10 && !abort; a++) {
for (b = 0; b < 10 && !abort; b++) {
if (condition) {
doSomeThing();
abort = true;
}
}
}
答案 8 :(得分:10)
我需要做类似的事情,但我选择不使用增强型for循环来完成它。
int s = type.size();
for (int i = 0; i < s; i++) {
for (int j = 0; j < t.size(); j++) {
if (condition) {
// do stuff after which you want
// to completely break out of both loops
s = 0; // enables the _main_ loop to terminate
break;
}
}
}
答案 9 :(得分:8)
我更喜欢在循环测试中添加一个显式的“退出”。它清楚地说明了 任何随意的读者,循环可能会提前终止。
boolean earlyExit = false;
for(int i = 0 ; i < 10 && !earlyExit; i++) {
for(int j = 0 ; i < 10 && !earlyExit; j++) { earlyExit = true; }
}
答案 10 :(得分:7)
Java 8 Stream
解决方案:
List<Type> types1 = ...
List<Type> types2 = ...
types1.stream()
.flatMap(type1 -> types2.stream().map(type2 -> new Type[]{type1, type2}))
.filter(types -> /**some condition**/)
.findFirst()
.ifPresent(types -> /**do something**/);
答案 11 :(得分:5)
通常在这种情况下,它会进入更有意义的逻辑范围,让我们说一些搜索或操纵一些迭代的“for”对象,所以我通常使用函数方法:
public Object searching(Object[] types) { // Or manipulating
List<Object> typesReferences = new ArrayList<Object>();
List<Object> typesReferences2 = new ArrayList<Object>();
for (Object type : typesReferences) {
Object o = getByCriterion(typesReferences2, type);
if(o != null) return o;
}
return null;
}
private Object getByCriterion(List<Object> typesReferences2, Object criterion) {
for (Object typeReference : typesReferences2) {
if(typeReference.equals(criterion)) {
// here comes other complex or specific logic || typeReference.equals(new Object())
return typeReference;
}
}
return null;
}
主要缺点:
专业人士:
所以它只是通过不同的方法处理案例。
这个问题的作者基本上是一个问题:你对这种方法有什么看法?
答案 12 :(得分:5)
您可以在不使用任何标签的情况下从所有循环中断:和标记。
这只是一个棘手的解决方案。
这里condition1是用于从循环K和J中断的条件。 而条件2是用于从循环K,J和I中断的条件。
例如:
public class BreakTesting {
public static void main(String[] args) {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
for (int k = 0; k < 9; k++) {
if (condition1) {
System.out.println("Breaking from Loop K and J");
k = 9;
j = 9;
}
if (condition2) {
System.out.println("Breaking from Loop K, J and I");
k = 9;
j = 9;
i = 9;
}
}
}
}
System.out.println("End of I , J , K");
}
}
答案 13 :(得分:3)
最简单的方法..
outerloop:
for(int i=0; i<10; i++){
// here we can break Outer loop by
break outerloop;
innerloop:
for(int i=0; i<10; i++){
// here we can break innerloop by
break innerloop;
}
}
答案 14 :(得分:3)
如果它在某个功能中,你为什么不把它归还:
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
return value;
}
}
}
答案 15 :(得分:3)
相当不寻常的方法,但就代码长度而言(不是性能),这是您可以做的最简单的事情:
for(int i = 0; i++; i < j) {
if(wanna exit) {
i = i + j; // if more nested, also add the
// maximum value for the other loops
}
}
答案 16 :(得分:3)
另一个解决方案,没有示例提及(它实际上在prod代码中工作)。
try {
for (Type type : types) {
for (Type t : types2) {
if (some condition #1) {
// Do something and break the loop.
throw new BreakLoopException();
}
}
}
}
catch (BreakLoopException e) {
// Do something on look breaking.
}
当然BreakLoopException
应该是内部的,私有的并且使用无堆栈跟踪加速:
private static class BreakLoopException extends Exception {
@Override
public StackTraceElement[] getStackTrace() {
return new StackTraceElement[0];
}
}
答案 17 :(得分:3)
使用标签。
INNER:for(int j = 0; j < numbers.length; j++) {
System.out.println("Even number: " + i + ", break from INNER label");
break INNER;
}
请参阅this article
答案 18 :(得分:2)
与@ 1800 INFORMATION建议一样,使用将内循环作为外循环条件的条件:
boolean hasAccess = false;
for (int i = 0; i < x && hasAccess == false; i++){
for (int j = 0; j < y; j++){
if (condition == true){
hasAccess = true;
break;
}
}
}
答案 19 :(得分:2)
boolean broken = false; // declared outside of the loop for efficiency
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
broken = true;
break;
}
}
if (broken) {
break;
}
}
答案 20 :(得分:2)
演示
public static void main(String[] args) {
outer:
while (true) {
while (true) {
break outer;
}
}
}
答案 21 :(得分:2)
标签中断概念用于在Java中中断嵌套循环,通过使用带标签的break,您可以在任何位置中断循环的嵌套。 范例1:
sudo systemctl enable myproject.service
sudo systemctl start myproject.service
sudo systemctl status myproject.service
假设有3个循环,而您想终止循环3: 示例2:
inactive (dead)
答案 22 :(得分:2)
for (int j = 0; j < 5; j++) //inner loop
应替换为
for (int j = 0; j < 5 && !exitloops; j++)
。
在这种情况下,如果条件为True
,则应退出完整的嵌套循环。但是,如果我们仅将exitloops
用于上loop
for (int i = 0; i < 5 && !exitloops; i++) //upper loop
然后内部循环将继续,因为没有额外的标志通知此内部循环退出。
示例:如果
i = 3
和j=2
则条件为false
。但是在内循环j=3
的下一次迭代中,条件(i*j)
变为9
,即true
,但内循环将一直持续到j
变为5
因此,它必须对内循环使用exitloops
。
boolean exitloops = false;
for (int i = 0; i < 5 && !exitloops; i++) { //here should exitloops as a Conditional Statement to get out from the loops if exitloops become true.
for (int j = 0; j < 5 && !exitloops; j++) { //here should also use exitloops as a Conditional Statement.
if (i * j > 6) {
exitloops = true;
System.out.println("Inner loop still Continues For i * j is => "+i*j);
break;
}
System.out.println(i*j);
}
}
答案 23 :(得分:2)
break
,continue
和label
的演示:
Java关键字break
和continue
具有默认值。它是最近的循环&#34;,今天,在使用Java几年之后,我就得到了它!
它似乎很少用,但很有用。
import org.junit.Test;
/**
* Created by cui on 17-5-4.
*/
public class BranchLabel {
@Test
public void test() {
System.out.println("testBreak");
testBreak();
System.out.println("testBreakLabel");
testBreakLabel();
System.out.println("testContinue");
testContinue();
System.out.println("testContinueLabel");
testContinueLabel();
}
/**
testBreak
a=0,b=0
a=0,b=1
a=1,b=0
a=1,b=1
a=2,b=0
a=2,b=1
a=3,b=0
a=3,b=1
a=4,b=0
a=4,b=1
*/
public void testBreak() {
for (int a = 0; a < 5; a++) {
for (int b = 0; b < 5; b++) {
if (b == 2) {
break;
}
System.out.println("a=" + a + ",b=" + b);
}
}
}
/**
testContinue
a=0,b=0
a=0,b=1
a=0,b=3
a=0,b=4
a=1,b=0
a=1,b=1
a=1,b=3
a=1,b=4
a=2,b=0
a=2,b=1
a=2,b=3
a=2,b=4
a=3,b=0
a=3,b=1
a=3,b=3
a=3,b=4
a=4,b=0
a=4,b=1
a=4,b=3
a=4,b=4
*/
public void testContinue() {
for (int a = 0; a < 5; a++) {
for (int b = 0; b < 5; b++) {
if (b == 2) {
continue;
}
System.out.println("a=" + a + ",b=" + b);
}
}
}
/**
testBreakLabel
a=0,b=0,c=0
a=0,b=0,c=1
* */
public void testBreakLabel() {
anyName:
for (int a = 0; a < 5; a++) {
for (int b = 0; b < 5; b++) {
for (int c = 0; c < 5; c++) {
if (c == 2) {
break anyName;
}
System.out.println("a=" + a + ",b=" + b + ",c=" + c);
}
}
}
}
/**
testContinueLabel
a=0,b=0,c=0
a=0,b=0,c=1
a=1,b=0,c=0
a=1,b=0,c=1
a=2,b=0,c=0
a=2,b=0,c=1
a=3,b=0,c=0
a=3,b=0,c=1
a=4,b=0,c=0
a=4,b=0,c=1
*/
public void testContinueLabel() {
anyName:
for (int a = 0; a < 5; a++) {
for (int b = 0; b < 5; b++) {
for (int c = 0; c < 5; c++) {
if (c == 2) {
continue anyName;
}
System.out.println("a=" + a + ",b=" + b + ",c=" + c);
}
}
}
}
}
答案 24 :(得分:2)
如果是新实现,您可以尝试将该逻辑重写为if-else_if-else语句。
if sum == target {
fmt.Println(curComb)
tmpCurComb := make([]int, len(curComb))
copy(tmpCurComb, curComb)
return [][]int{tmpCurComb}
否则,您可以尝试在发生特殊情况时设置标志,并在每个循环条件中检查该标志。
while(keep_going) {
if(keep_going && condition_one_holds) {
// Code
}
if(keep_going && condition_two_holds) {
// Code
}
if(keep_going && condition_three_holds) {
// Code
}
if(keep_going && something_goes_really_bad) {
keep_going=false;
}
if(keep_going && condition_four_holds) {
// Code
}
if(keep_going && condition_five_holds) {
// Code
}
}
下面!因此,虽然简单的中断不起作用,但可以使用something_bad_has_happened = false;
while(something is true && !something_bad_has_happened){
// Code, things happen
while(something else && !something_bad_has_happened){
// Lots of code, things happens
if(something happened){
-> Then control should be returned ->
something_bad_has_happened=true;
continue;
}
}
if(something_bad_has_happened) { // The things below will not be executed
continue;
}
// Other things may happen here as well, but they will not be executed
// once control is returned from the inner cycle.
}
来使其工作。
如果您只是将逻辑从一种编程语言移植到Java,并且只是想让这项工作正常,您可以尝试使用labels。
答案 25 :(得分:1)
当您需要退出多个循环时,单独使用'break'关键字是不合适的方法。 您可以退出立即循环 无论您的语句有多少个循环。 您可以在标签上使用“ break”! 在这里,我使用了标签“ abc” 您可以在Java中的任何函数内编写以下代码
此代码显示了如何从最外层循环退出
abc:
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
for (int k = 0; k < 10; k++) {
if (k == 1){
break abc;
}
}
}
}
您还可以使用break语句从嵌套循环的任何循环中退出。
for (int i = 0; i < 10; i++) {
abc:for (int j = 0; j < 10; j++) {
for (int k = 0; k < 10; k++) {
if (k == 1){
break abc;
}
}
}
}
以下代码显示了从最内层循环退出的示例。 在其他工作中,执行以下代码后,您将处于'k'变量循环的外部,而仍位于'j'和'i'变量循环的内部。
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
for (int k = 0; k < 10; k++) {
if (k == 1){
break;
}
}
}
}
答案 26 :(得分:1)
您可以执行以下操作:
将本地变量设置为false
在第一个循环中设置变量true
,当你想要破解时
然后你可以检查外部循环,是否设置条件然后从外部循环中断。
boolean isBreakNeeded = false;
for (int i = 0; i < some.length; i++) {
for (int j = 0; j < some.lengthasWell; j++) {
//want to set variable if (){
isBreakNeeded = true;
break;
}
if (isBreakNeeded) {
break; //will make you break from the outer loop as well
}
}
答案 27 :(得分:1)
在某些情况下,我们可以在这里有效地使用while
循环。
Random rand = new Random();
// Just an example
for (int k = 0; k < 10; ++k) {
int count = 0;
while (!(rand.nextInt(200) == 100)) {
count++;
}
results[k] = count;
}
答案 28 :(得分:1)
甚至为外循环创建一个标志,并在每次执行内循环后检查它是否可以作为答案。
像这样:
for (Type type : types) {
boolean flag=false;
for (Type t : types2) {
if (some condition) {
// Do something and break...
flag=true;
break; // Breaks out of the inner loop
}
}
if(flag)
break;
}
答案 29 :(得分:0)
Java不具有C ++中的goto功能。但是,goto
仍然是Java中的保留关键字。他们可能会在将来实施它。对于您的问题,答案是Java中有一个称为label的东西,您可以在其中应用continue
和break
语句。在下面找到代码:
public static void main(String ...args) {
outerLoop: for(int i=0;i<10;i++) {
for(int j=10;j>0;j--) {
System.out.println(i+" "+j);
if(i==j) {
System.out.println("Condition Fulfilled");
break outerLoop;
}
}
}
System.out.println("Got out of the outer loop");
}
答案 30 :(得分:0)
下面是一个示例,其中只要满足条件,“ break”语句就会将光标移出for循环。
public class Practice3_FindDuplicateNumber {
public static void main(String[] args) {
Integer[] inp = { 2, 3, 4, 3, 3 };
Integer[] aux_arr = new Integer[inp.length];
boolean isduplicate = false;
for (int i = 0; i < aux_arr.length; i++) {
aux_arr[i] = -1;
}
outer: for (int i = 0; i < inp.length; i++) {
if (aux_arr[inp[i]] == -200) {
System.out.println("Duplicate Found at index: " + i + " Carrying value: " + inp[i]);
isduplicate = true;
break outer;
} else {
aux_arr[inp[i]] = -200;
}
}
for (Integer integer : aux_arr) {
System.out.println(integer);
}
if (isduplicate == false) {
System.out.println("No Duplicates!!!!!");
} else {
System.out.println("Duplicates!!!!!");
}
}
}
答案 31 :(得分:0)
使用terminate called after throwing an instance of 'dmlc::Error'
what(): [13:17:26] /workspace/src/common/common.h:41: /workspace/src/predictor/../common/device_helpers.cuh: 113: initialization error
Stack trace:
[bt] (0) /home/geiringe/miniconda3/envs/env-74-conda-pip-090/xgboost/libxgboost.so(dh::ThrowOnCudaError(cudaError, char const*, int)+0x3b5) [0x7f5bd894bb95]
[bt] (1) /home/geiringe/miniconda3/envs/env-74-conda-pip-090/xgboost/libxgboost.so(dh::MaxSharedMemory(int)+0x24) [0x7f5bd89ce0a4]
[bt] (2) /home/geiringe/miniconda3/envs/env-74-conda-pip-090/xgboost/libxgboost.so(+0x30f1a7) [0x7f5bd89ce1a7]
[bt] (3) /home/geiringe/miniconda3/envs/env-74-conda-pip-090/bin/../lib/libgomp.so.1(GOMP_parallel+0x42) [0x7f5c4401ce92]
[bt] (4) /home/geiringe/miniconda3/envs/env-74-conda-pip-090/xgboost/libxgboost.so(void dh::ExecuteIndexShards<xgboost::predictor::GPUPredictor::DeviceShard, xgboost::predictor::GPUPredictor::ConfigureShards(xgboost::GPUSet)::{lambda(unsigned long, xgboost::predictor::GPUPredictor::DeviceShard&)#1}>(std::vector<xgboost::predictor::GPUPredictor::DeviceShard, std::allocator<std::vector> >*, xgboost::predictor::GPUPredictor::ConfigureShards(xgboost::GPUSet)::{lambda(unsigned long, xgboost::predictor::GPUPredictor::DeviceShard&)#1})+0xab) [0x7f5bd89ce78b]
[bt] (5) /home/geiringe/miniconda3/envs/env-74-conda-pip-090/xgboost/libxgboost.so(xgboost::predictor::GPUPredictor::Init(std::vector<std::pair<std::string, std::string>, std::allocator<std::pair<std::string, std::string> > > const&, std::vector<std::shared_ptr<xgboost::DMatrix>, std::allocator<std::shared_ptr<xgboost::DMatrix> > > const&)+0x69e) [0x7f5bd89d41fe]
[bt] (6) /home/geiringe/miniconda3/envs/env-74-conda-pip-090/xgboost/libxgboost.so(xgboost::gbm::GBTree::Configure(std::vector<std::pair<std::string, std::string>, std::allocator<std::pair<std::string, std::string> > > const&)+0x472) [0x7f5bd8844822]
[bt] (7) /home/geiringe/miniconda3/envs/env-74-conda-pip-090/xgboost/libxgboost.so(void xgboost::GradientBooster::Configure<std::_Rb_tree_iterator<std::pair<std::string const, std::string> > >(std::_Rb_tree_iterator<std::pair<std::string const, std::string> >, std::_Rb_tree_iterator<std::pair<std::string const, std::string> >)+0xd1) [0x7f5bd884d711]
[bt] (8) /home/geiringe/miniconda3/envs/env-74-conda-pip-090/xgboost/libxgboost.so(xgboost::LearnerImpl::LazyInitModel()+0x45e) [0x7f5bd885508e]
相当容易,您可以使用标签将外部循环从内部循环中断开,请考虑以下示例
label
另一种方法是使用中断变量/标志来跟踪所需的中断。请考虑以下示例。
public class Breaking{
public static void main(String[] args) {
outerscope:
for (int i=0; i < 5; i++) {
for (int j=0; j < 5; j++) {
if (condition) {
break outerscope;
}
}
}
}
}
但是,我更喜欢使用第一种方法。
答案 32 :(得分:0)
boolean condition = false;
for (Type type : types) {
for (int i = 0; i < otherTypes.size && !condition; i ++) {
condition = true; // If your condition is satisfied
}
}
使用condition
作为处理完成后的标志。然后内部循环仅在条件未满足时继续。无论哪种方式,外部循环将保持chuggin&#39;。
答案 33 :(得分:-1)
你只需使用标签打破内循环
public class Test {
public static void main(String[] args) {
outerloop:
for (int i=0; i < 5; i++) {
for (int j=0; j < 5; j++) {
if (i * j > 6) {
System.out.println("Breaking");
break outerloop;
}
System.out.println(i + " " + j);
}
}
System.out.println("Done");
}
}
答案 34 :(得分:-1)
通过检查内部循环的变量,检查内部循环是否通过if语句退出。您还可以创建另一个变量(如布尔值)来检查内循环是否已退出。
在这个例子中,它使用内部循环的变量来检查它是否已经退出:
int i, j;
for(i = 0; i < 7; i++){
for(j = 0; j < 5; j++) {
if (some condition) {
// Do something and break...
break; // Breaks out of the inner loop
}
}
if(j < 5){ // Checks if inner loop wasn't finished
break; // Breaks out of the outer loop
}
}
答案 35 :(得分:-9)
我觉得使用标签会使代码看起来非常像goto语句。这只是一个想法。
相反,在内部for
循环中抛出异常,并使用try catch块封装两个for
循环。
像
这样的东西try {
// ...
for(Object outerForLoop : objectsOuter) {
// ...
for (Object innerForLoop : objectsInner) {
// ...
if (isConditionTrue)
throw new WrappedException("With some useful message. Probably some logging as well.");
}
}
catch (WrappedException) {
// Do something awesome or just don't do anything to swallow the exception.
}
只是一个想法。我更喜欢这个代码,因为当它在生产中运行时,它为我提供了更好的可记录性(就像这个单词一样)。