Skip to content

Commit 6ad5f4c

Browse files
committed
feat(streams): add comprehensive demo of terminal operations in Java Streams
What - Introduced `TerminalOps.java` to showcase all major terminal operations in Java Streams. - Implemented examples with `List`, `Stream`, and Strings to demonstrate: 1. **collect** → gather results into collections (`toList`, `Collectors.toList`). 2. **forEach / forEachOrdered** → process elements sequentially or with order guarantees. 3. **reduce** → accumulate elements into a single result (e.g., sum). 4. **count** → count number of elements in stream. 5. **anyMatch / allMatch / noneMatch** → short-circuiting predicate-based checks. 6. **findFirst / findAny** → retrieve elements, important for sequential vs parallel streams. 7. **toArray** → convert stream elements into an array. 8. **min / max** → find smallest or largest element with comparators. 9. **parallel stream behavior** → difference between `forEach` and `forEachOrdered`. - Added multiple applied use cases: - Filtering and collecting names by length. - Squaring and sorting numbers. - Summing integers via `reduce`. - Counting occurrences of a character in a String (`chars()` stream). - Demonstrating **stream reuse limitation** (consumed stream cannot be reused). Why - Terminal operations are essential because they **trigger execution** of stream pipelines. - Without a terminal operation, intermediate ops remain lazy and never execute. - This file provides a consolidated tutorial for developers to understand: - Different result types: collections, primitives, optionals. - Short-circuiting behavior (`anyMatch`, `findFirst`). - Parallel stream ordering guarantees. Logic 1. **collect** - `list.stream().skip(1).collect(Collectors.toList())` → gathers elements into a collection. - Modern shorthand: `list.stream().skip(1).toList()` (Java 16+). 2. **forEach / forEachOrdered** - `forEach` executes actions on each element (order not guaranteed in parallel). - `forEachOrdered` enforces encounter order in parallel streams. 3. **reduce** - Combines elements (e.g., sum, product, concatenation). - Returns an `Optional<T>` if identity not provided. 4. **count** - Efficient terminal op to count elements (long value). 5. **anyMatch / allMatch / noneMatch** - Predicate checks with short-circuiting (pipeline halts early if result is known). 6. **findFirst / findAny** - `findFirst`: deterministic (first element in stream). - `findAny`: may return any element (useful in parallel streams for efficiency). 7. **toArray** - Collects stream elements into an array (`Object[]` or typed array). 8. **min / max** - Finds extreme values using a comparator or natural order. 9. **Parallel ordering** - Showcases how unordered parallel execution differs between `forEach` and `forEachOrdered`. 10. **Stream reuse limitation** - Once consumed by a terminal op, a stream cannot be reused → attempting leads to `IllegalStateException`. Real-world applications - **Aggregation pipelines**: Summing, counting, min/max in reporting. - **Search operations**: Quickly finding first/any matching element. - **Collections transformation**: Gathering processed data into Lists, Sets, or Maps. - **Parallelism**: Leveraging short-circuiting and ordering in parallel stream processing. - **String analysis**: Counting frequency of characters or substrings. - **Data integrity**: Teaching stream reuse rules prevents runtime exceptions. Notes - Complements `IntermediateOps.java`: together, they cover full lifecycle of stream pipelines. - Emphasizes **lazy vs eager** evaluation boundary. - Acts as both runnable examples and a learning reference for terminal stream operations. Signed-off-by: https://github.com/Someshdiwan <[email protected]>
1 parent 8bfab8c commit 6ad5f4c

File tree

1 file changed

+29
-31
lines changed
  • Java 8 Crash Course/Java 8 Streams/Intermediate and Terminal Operations/src

1 file changed

+29
-31
lines changed

JAVA8/StreamsInJAVA/src/TerminalOps.java renamed to Java 8 Crash Course/Java 8 Streams/Intermediate and Terminal Operations/src/TerminalOps.java

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,50 +7,47 @@
77

88
public class TerminalOps {
99
public static void main(String[] args) {
10-
1110
List<Integer> list = Arrays.asList(1, 2, 3);
1211

13-
// 1. collect
12+
// 1. collect → gathers stream elements into a collection (List, Set, Map, etc.)
1413
list.stream().skip(1).collect(Collectors.toList());
15-
list.stream().skip(1).toList();
14+
list.stream().skip(1).toList(); // Java 16+ shorthand
1615

17-
// 2. forEach
16+
// 2. forEach → performs an action for each element
1817
list.stream().forEach(x -> System.out.println(x));
1918

20-
// 3. reduce : Combines elements to produce a single result
19+
// 3. reduce → combines elements to produce a single result
2120
Optional<Integer> optionalInteger = list.stream().reduce(Integer::sum);
22-
System.out.println(optionalInteger.get());
23-
24-
// 4. count
21+
System.out.println(optionalInteger.get()); // sum of all elements
2522

26-
// 5. anyMatch, allMatch, noneMatch
23+
// 4. count → returns number of elements in the stream
24+
System.out.println("Count: " + list.stream().count());
2725

28-
boolean b = list.stream().anyMatch(x -> x % 2 == 0);
26+
// 5. anyMatch, allMatch, noneMatch → short-circuiting terminal ops
27+
boolean b = list.stream().anyMatch(x -> x % 2 == 0); // any element even?
2928
System.out.println(b);
30-
boolean b1 = list.stream().allMatch(x -> x > 0);
29+
boolean b1 = list.stream().allMatch(x -> x > 0); // all elements > 0?
3130
System.out.println(b1);
32-
boolean b2 = list.stream().noneMatch(x -> x < 0);
31+
boolean b2 = list.stream().noneMatch(x -> x < 0); // none element negative?
3332
System.out.println(b2);
3433

35-
// 6. findFirst, findAny
36-
System.out.println(list.stream().findFirst().get());
37-
System.out.println(list.stream().findAny().get());
38-
39-
// 7. toArray()
34+
// 6. findFirst, findAny → retrieve elements
35+
System.out.println(list.stream().findFirst().get()); // always first element
36+
System.out.println(list.stream().findAny().get()); // may return any (parallel streams)
4037

38+
// 7. toArray() → collect elements into an array
4139
Object[] array = Stream.of(1, 2, 3).toArray();
4240

43-
// 8. min / max
41+
// 8. min / max → compute smallest/largest element
4442
System.out.println("max: " + Stream.of(2, 44, 69).max((o1, o2) -> o2 - o1));
4543
System.out.println("min: " + Stream.of(2, 44, 69).min(Comparator.naturalOrder()));
4644

47-
// 9. forEachOrdered
45+
// 9. forEachOrdered → maintains encounter order (important in parallel streams)
4846
List<Integer> numbers0 = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
4947
System.out.println("Using forEach with parallel stream:");
50-
numbers0.parallelStream().forEach(System.out::println);
48+
numbers0.parallelStream().forEach(System.out::println); // order not guaranteed
5149
System.out.println("Using forEachOrdered with parallel stream:");
52-
numbers0.parallelStream().forEachOrdered(System.out::println);
53-
50+
numbers0.parallelStream().forEachOrdered(System.out::println); // maintains order
5451

5552

5653
// Example: Filtering and Collecting Names
@@ -65,19 +62,20 @@ public static void main(String[] args) {
6562
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
6663
System.out.println(integers.stream().reduce(Integer::sum).get());
6764

68-
// Example: Counting Occurrences of a Character
65+
// Example: Counting Occurrences of a Character
6966
String sentence = "Hello world";
70-
System.out.println(sentence.chars().filter(x -> x == 'l').count());
67+
System.out.println(sentence.chars().filter(x -> x == 'l').count()); // count 'l'
7168

72-
// Example
69+
// Example: Stream Reuse Limitation
7370
// Streams cannot be reused after a terminal operation has been called
7471
Stream<String> stream = names.stream();
7572
stream.forEach(System.out::println);
76-
// List<String> list1 = stream.map(String::toUpperCase).toList(); // exception
77-
78-
// stateful & stateless
79-
80-
73+
// List<String> list1 = stream.map(String::toUpperCase).toList(); // throws IllegalStateException
8174

75+
// NOTE:
76+
// - Terminal operations = trigger execution of the stream pipeline.
77+
// - Once terminal op is invoked, the stream is consumed and cannot be reused.
78+
// - Some terminal ops are "short-circuiting" (anyMatch, findFirst, etc.).
79+
// - Distinction: stateful Vs stateless operations
8280
}
83-
}
81+
}

0 commit comments

Comments
 (0)