forEach() is a method that performs a given action on every element of a source, existing both as a default method on Iterable (for collections) and as a terminal operation on Stream, letting you iterate without writing an explicit for-loop.
Key Points: • As a default method on Iterable, forEach(Consumer) lets you call list.forEach(...) directly on any Collection without converting it to a stream first. • As a Stream terminal operation, forEach() consumes the stream and applies the given Consumer to each element that survives the pipeline. • It takes a Consumer<T>, a functional interface whose accept() method returns nothing, making it suited for side-effecting actions like printing or logging. • forEach() on a sequential stream processes elements in encounter order, but forEachOrdered() should be used instead of forEach() on parallel streams when order must be preserved. • Because forEach() is designed for side effects, it's generally discouraged for transforming data — map() and collect() are the right tools when you need a result rather than an action.
Example: list.forEach(System.out::println) replaces a traditional for (String s : list) { System.out.println(s); } loop with a single, declarative line.
Code Example:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(name -> System.out.println("Hello, " + name));Interview Tip: A concise interview answer is:
"forEach() applies a Consumer to every element, either directly on a Collection through the Iterable default method or as a terminal operation at the end of a stream pipeline. It cuts down boilerplate compared to a classic for-loop, but since it's meant for side effects rather than producing a value, I still reach for map() and collect() when I actually need a transformed result."