Creating streams:

java

shapes.stream()              // → Stream<Shape>
Stream.of(1, 2, 3)          // → Stream<Integer>
Stream.empty()               // → Stream<T>
IntStream.range(0, 5)        // → IntStream
IntStream.rangeClosed(0, 5)  // → IntStream

Intermediate operations (all return a stream):

java

// filter — keep elements that match
shapes.stream()
    .filter(s -> s.getArea() > 10)
// Stream<Shape> → Stream<Shape>
 
// map — transform each element
shapes.stream()
    .map(s -> s.getArea())
// Stream<Shape> → Stream<Double>
 
// flatMap — flatten nested streams
nested.stream()
    .flatMap(list -> list.stream())
// Stream<List<Integer>> → Stream<Integer>
 
// sorted
shapes.stream()
    .sorted(Comparator.comparing(Shape::getArea))
// Stream<Shape> → Stream<Shape>
 
// distinct
Stream.of(1, 2, 2, 3)
    .distinct()
// Stream<Integer> → Stream<Integer>
 
// peek
shapes.stream()
    .peek(s -> System.out.println(s))
// Stream<Shape> → Stream<Shape>
 
// limit
shapes.stream()
    .limit(3)
// Stream<Shape> → Stream<Shape>
 
// skip
shapes.stream()
    .skip(2)
// Stream<Shape> → Stream<Shape>
 
// takeWhile
Stream.of(1, 2, 3, 4, 5)
    .takeWhile(n -> n < 4)
// Stream<Integer> → Stream<Integer>
 
// dropWhile
Stream.of(1, 2, 3, 4, 5)
    .dropWhile(n -> n < 4)
// Stream<Integer> → Stream<Integer>
 
// mapToInt
shapes.stream()
    .mapToInt(s -> (int) s.getArea())
// Stream<Shape> → IntStream
 
// mapToDouble
shapes.stream()
    .mapToDouble(s -> s.getArea())
// Stream<Shape> → DoubleStream

Terminal operations (end the stream):

java

// collect → whatever you collect into
shapes.stream()
    .collect(Collectors.toList())
// Stream<Shape> → List<Shape>
 
// toList → unmodifiable List<T>
shapes.stream()
    .toList()
// Stream<Shape> → List<Shape>
 
// forEach → void
shapes.stream()
    .forEach(s -> System.out.println(s))
// Stream<Shape> → void
 
// count → long
shapes.stream()
    .count()
// Stream<Shape> → long
 
// reduce → T or Optional<T>
shapes.stream()
    .map(Shape::getArea)
    .reduce(0.0, (a, b) -> a + b)
// Stream<Double> → Double (with identity)
 
shapes.stream()
    .map(Shape::getArea)
    .reduce((a, b) -> a + b)
// Stream<Double> → Optional<Double> (without identity)
 
// min → Optional<T>
shapes.stream()
    .min(Comparator.comparing(Shape::getArea))
// Stream<Shape> → Optional<Shape>
 
// max → Optional<T>
shapes.stream()
    .max(Comparator.comparing(Shape::getArea))
// Stream<Shape> → Optional<Shape>
 
// findFirst → Optional<T>
shapes.stream()
    .findFirst()
// Stream<Shape> → Optional<Shape>
 
// findAny → Optional<T>
shapes.stream()
    .findAny()
// Stream<Shape> → Optional<Shape>
 
// anyMatch → boolean
shapes.stream()
    .anyMatch(s -> s.getColor().equals("red"))
// Stream<Shape> → boolean
 
// allMatch → boolean
shapes.stream()
    .allMatch(s -> s.getArea() > 0)
// Stream<Shape> → boolean
 
// noneMatch → boolean
shapes.stream()
    .noneMatch(s -> s.getColor().equals("green"))
// Stream<Shape> → boolean
 
// toArray → T[]
shapes.stream()
    .toArray(Shape[]::new)
// Stream<Shape> → Shape[]

Primitive stream extras (IntStream / DoubleStream):

java

// sum → int or double
shapes.stream()
    .mapToDouble(Shape::getArea)
    .sum()
// DoubleStream → double
 
// average → OptionalDouble
shapes.stream()
    .mapToDouble(Shape::getArea)
    .average()
// DoubleStream → OptionalDouble
 
// boxed — convert back to object stream
IntStream.range(0, 5)
    .boxed()
// IntStream → Stream<Integer>