Appearance
Lesson 04 · Optional & Primitive Streams
Objectives
After this lesson you will be able to:
- Use
Optionalcorrectly (map,filter,orElse,orElseGet,orElseThrow). - Use the primitive streams
IntStream/LongStream/DoubleStream. - Get summary statistics and convert between object and primitive streams.
Optional
Optional<T> models "a value or nothing" without null. Build it, transform it, then extract a value with a fallback.
java
Optional<String> o = Optional.of("hi"); // of(null) throws NPE
Optional<String> e = Optional.empty();
Optional<String> n = Optional.ofNullable(maybeNull);
o.map(String::length).filter(len -> len > 1); // chainable, stays Optional
o.orElse("default"); // fallback value
o.orElseGet(() -> compute()); // fallback supplier (lazy)
o.orElseThrow(); // NoSuchElementException if empty
o.ifPresent(System.out::println);Exam trap
Optional.get() on an empty Optional throws NoSuchElementException — prefer orElseThrow/ orElse. orElse(x) always evaluates x, even when the value is present; orElseGet(supplier) runs the supplier only when empty (use it when the fallback is expensive). Optional.of(null) throws NPE — use ofNullable.
Primitive streams
IntStream, LongStream, and DoubleStream avoid boxing and add numeric operations (sum, average, max, range).
java
int sum = IntStream.rangeClosed(1, 5).sum(); // 15 (1..5 inclusive)
OptionalDouble avg = IntStream.of(1, 2, 3).average(); // OptionalDouble[2.0]
int[] arr = IntStream.range(0, 3).toArray(); // {0,1,2}Gotcha
range(a, b) is end-exclusive; rangeClosed(a, b) includes b. sum() on an IntStream returns an int (can overflow), but average()/max() return OptionalDouble/OptionalInt because the stream may be empty.
Converting between stream kinds
java
List<String> names = ...;
int totalLen = names.stream().mapToInt(String::length).sum(); // Stream<String> → IntStream
IntSummaryStatistics stats = names.stream().mapToInt(String::length).summaryStatistics();
stats.getMax(); stats.getAverage(); stats.getCount();
Stream<Integer> boxed = IntStream.range(0, 3).boxed(); // IntStream → Stream<Integer>SDET note
summaryStatistics() gives count, sum, min, max, and average in one pass — handy for asserting aggregate properties of generated test data without writing several loops.
Key Takeaways
Optionalreplacesnull: build withof/ofNullable/empty; transform withmap/filter; extract withorElse/orElseGet/orElseThrow.get()on empty throws.orElseis eager,orElseGetis lazy — matters when the fallback is costly.- Primitive streams (
IntStream/…) avoid boxing and addsum/average/range/rangeClosed(range is exclusive, rangeClosed inclusive). - Convert with
mapToInt/boxed;summaryStatistics()yields count/sum/min/max/avg in one pass.
Lesson Quiz
What does Optional.empty().get() do?
Difference between orElse and orElseGet?
What is IntStream.range(1, 5).sum()?
Why does IntStream.of(1,2,3).average() return OptionalDouble?
What does Optional.of(null) do?
Next: Module 06 Mini-Exam. Run the matching code in labs/src/main/java/com/jse21/m06_streams/.