Else 被简单地跳过,但只是有时
Else is simply skipped, but only sometimes
private int bkicalc(int i, List<Integer> history) {
List<Integer> subList = history.subList(history.size()-1 - i, history.size()-1);
Set<Integer> uniliste = new HashSet<Integer>(subList);
if (uniliste.size() == 4) {
if (i>5) {
System.out.println(i);
}
return i;
} else {
this.bkicalc(i + 1, history);
}
System.out.println("else was skipped");
return 404;
}
您好,这个方法在 for 循环中被访问了 1000 次,其中有 1/10 的次数跳过了 else 和 returns 404。我无法向自己解释为什么会这样。
希望你能帮帮我。
您 return 来自 if
分支,但不是 else
分支。因此,诊断和 404 return 并不表示 else
被跳过,而是 采取 。 else
分支递归是无关紧要的:除非从递归调用中抛出异常,否则该调用最终将 return,此时控制只是从 else
块中传递出来。
看起来您可能希望在 else
分支中 return 递归调用的结果:
private int bkicalc(int i, List<Integer> history) {
List<Integer> subList = history.subList(history.size()-1 - i, history.size()-1);
Set<Integer> uniliste = new HashSet<Integer>(subList);
if (uniliste.size() == 4) {
if (i>5) {
System.out.println(i);
}
return i;
} else {
return this.bkicalc(i + 1, history); // <-- here
}
assert false : "unreachable";
return 404;
}
您甚至可能会发现编译器实际上将 return 404
标记为无法访问。
另请注意,您的子列表的范围有点令人惊讶。提供给 List.subList()
的上限是 exclusive,不包含在内,因此您一直在考虑中忽略 history
的最后一个元素。如果这是故意的,那么添加一个代码注释是明智的。
此外,如果 history
实际上总体上不包含至少 4 个不同的元素,那么在一定数量的递归之后,此方法将失败并返回 IndexOutOfBoundsException
。如果它最初不包含至少 5 个元素(记住一个被忽略),这当然肯定会发生。
最后,递归似乎很浪费,而且造成了不必要的混乱。出于各种原因,迭代方法会更好。 (几乎总是如此。)示例:
private int bkicalc(int i, List<Integer> history) {
if (history.size() >= 5) {
Set<Integer> uniliste = new HashSet<Integer>(
history.subList(history.size() - 5, history.size() - 1));
ListIterator<Integer> iterator = history.listIterator(history.size() - 5);
while (uniliste.size() < 4 && iterator.hasPrevious()) {
uniliste.add(iterator.previous());
}
if (uniliste.size() == 4) {
int i = history.size() - 1 - iterator.nextIndex();
if (i > 5) {
System.out.println(i);
}
return i;
}
}
// Fewer than 4 distinct elements (ignoring the last)
return -1;
}
private int bkicalc(int i, List<Integer> history) {
List<Integer> subList = history.subList(history.size()-1 - i, history.size()-1);
Set<Integer> uniliste = new HashSet<Integer>(subList);
if (uniliste.size() == 4) {
if (i>5) {
System.out.println(i);
}
return i;
} else {
this.bkicalc(i + 1, history);
}
System.out.println("else was skipped");
return 404;
}
您好,这个方法在 for 循环中被访问了 1000 次,其中有 1/10 的次数跳过了 else 和 returns 404。我无法向自己解释为什么会这样。
希望你能帮帮我。
您 return 来自 if
分支,但不是 else
分支。因此,诊断和 404 return 并不表示 else
被跳过,而是 采取 。 else
分支递归是无关紧要的:除非从递归调用中抛出异常,否则该调用最终将 return,此时控制只是从 else
块中传递出来。
看起来您可能希望在 else
分支中 return 递归调用的结果:
private int bkicalc(int i, List<Integer> history) {
List<Integer> subList = history.subList(history.size()-1 - i, history.size()-1);
Set<Integer> uniliste = new HashSet<Integer>(subList);
if (uniliste.size() == 4) {
if (i>5) {
System.out.println(i);
}
return i;
} else {
return this.bkicalc(i + 1, history); // <-- here
}
assert false : "unreachable";
return 404;
}
您甚至可能会发现编译器实际上将 return 404
标记为无法访问。
另请注意,您的子列表的范围有点令人惊讶。提供给 List.subList()
的上限是 exclusive,不包含在内,因此您一直在考虑中忽略 history
的最后一个元素。如果这是故意的,那么添加一个代码注释是明智的。
此外,如果 history
实际上总体上不包含至少 4 个不同的元素,那么在一定数量的递归之后,此方法将失败并返回 IndexOutOfBoundsException
。如果它最初不包含至少 5 个元素(记住一个被忽略),这当然肯定会发生。
最后,递归似乎很浪费,而且造成了不必要的混乱。出于各种原因,迭代方法会更好。 (几乎总是如此。)示例:
private int bkicalc(int i, List<Integer> history) {
if (history.size() >= 5) {
Set<Integer> uniliste = new HashSet<Integer>(
history.subList(history.size() - 5, history.size() - 1));
ListIterator<Integer> iterator = history.listIterator(history.size() - 5);
while (uniliste.size() < 4 && iterator.hasPrevious()) {
uniliste.add(iterator.previous());
}
if (uniliste.size() == 4) {
int i = history.size() - 1 - iterator.nextIndex();
if (i > 5) {
System.out.println(i);
}
return i;
}
}
// Fewer than 4 distinct elements (ignoring the last)
return -1;
}