Question 1
Stream.iterate is called with three arguments. What does this program print?
import java.util.stream.*;
public class Main {
public static void main(String[] args) {
String s = Stream.iterate(1, i -> i < 20, i -> i * 3)
.map(String::valueOf)
.collect(Collectors.joining("-"));
System.out.println(s);
}
}A. 3-9
Wrong: this assumes the seed is not part of the stream, as if next were applied once before the first emission. The seed is always the first candidate element, so 1 is emitted.
B. 1-3-9Correct answer
Correct: the three-argument iterate tests the predicate before each emission including the seed, so 1, 3, 9 pass i < 20 and 27 fails; joined with dashes they give 1-3-9.
C. The program never terminates because Stream.iterate produces an infinite stream
Wrong: this describes the two-argument iterate(seed, next), which is infinite and needs a short-circuiting op. The three-argument overload is bounded by its predicate and is finite.
D. 1-3-9-27
Wrong: this treats the predicate as a do-while condition - emit first, test afterwards - so 27 slips out before the check fails. The predicate is a hasNext, checked before emission.
Explanation
Trace: the three-argument Stream.iterate(seed, hasNext, next) is the stream analogue of a for loop — the predicate is tested before each element is emitted, including the seed. So it tests 1 (< 20, emit), applies next to get 3 (< 20, emit), then 9 (< 20, emit), then 27, which fails i < 20, so the stream ends without emitting it. Three elements survive, map stringifies them and joining("-") glues them with a single dash between neighbours: 1-3-9.
Why the others are wrong:
1-3-9-27 treats the predicate as a do-while condition — emit first, test afterwards — so 27 slips out before the check fails. The predicate is a hasNext, checked before emission.
3-9 assumes the seed is not part of the stream, as if next were applied once before the first emission. The seed is always the first candidate element.
The program never terminates because Stream.iterate produces an infinite stream describes the two-argument iterate(seed, next), which is indeed infinite and needs a short-circuiting op such as limit. The three-argument overload (Java 9) is bounded by its predicate and is a finite stream.
Exam tip: Stream.iterate(1, i -> i < 20, i -> i * 3) maps one-to-one onto for (int i = 1; i < 20; i *= 3) — seed, condition, update, condition checked first. Reverse trap: with only two arguments the stream is infinite, and a terminal op like collect or count on it hangs forever.