Checked exceptions
The action can throw a checked exception. It reaches the caller unchanged, and the loop stops.
Why it matters
IntStream.range(0, n).forEach(...) takes an IntConsumer, which cannot throw checked exceptions. The usual workaround wraps and unwraps.
STREAMS
IntStream.range(0, 3).forEach(i -> {
try {
Files.createFile(path(i));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
});
JAVA-REPEAT
repeat(3, i -> Files.createFile(path(i)));
// throws IOException
How the type is inferred
repeat is declared <E extends Throwable> ... throws E. The compiler picks E from what the lambda throws:
- Throws nothing checked:
EisRuntimeException; nothing to declare. - Throws one checked type:
Eis that type, for exampleIOException. - Throws several:
Eis their common supertype, oftenException. Catch inside the action if you need them apart.
A failure stops the loop
repeat(5, i -> {
ran.add(i);
if (i == 1) throw new IOException("ERROR!");
});
// ran == [0, 1]; the IOException reaches the caller
0ran
1threw
2skipped
3skipped
4skipped
Keep going after a failure
To run every iteration regardless, catch inside the action and collect what failed.
List<IOException> failures = new ArrayList<>();
repeat(5, i -> {
try {
Files.createFile(path(i));
} catch (IOException e) {
failures.add(e);
}
});