Streams API Intermediate Operations
Streams API Intermediate Operations
IP
ND
SA
🔹 Key Characteristics:
● Lazy Evaluation: Intermediate operations don’t do anything until a terminal
operation is called.
● Chainable: You can link multiple intermediate operations together (fluent
style).
● Return a Stream: They always return a new stream, allowing further operations.
Operations
🔹 1.filter()
✦ Purpose: Filters elements based on a predicate or given condition.
IP
✦ Syntax: Stream<T> filter(Predicate<? super T> predicate)
🔸 Example_1:
ND
List<String> names = Arrays.asList("John", "Jane", "Tom", "Jake");
names.stream()
.filter(name -> name.startsWith("J"))
.forEach(System.out::println);
🔸 Example_2:
SA
🔹 2.map()
✦ Purpose:
● The map() method is an intermediate operation in the Java Stream API.It is
used to transform (or map) each element of the stream from type T to
another type R.
● It returns a new stream consisting of the results of applying the given
Function to the elements of the original stream.
✦ Syntax: <R> Stream<R> map(Function<? super T, ? extends R> mapper)
► Breakdown of the Signature:
● <R> – This denotes a generic type of the result. It means that after
IP
mapping, each element in the new stream will be of type R.
● Function<? super T, ? extends R> – This is the functional interface used
to perform the transformation:
● T is the input type (type of elements in the original stream).
● R is the output type (type of elements in the resulting stream).
ND
● ? super T allows the function to accept T or any of its supertypes.
● ? extends R allows the result to be a subtype of R.
🔸 Example_1: Convert Strings to Uppercase
List<String> names = Arrays.asList("alice", "bob", "charlie");
SA
► Note:
● String::toUpperCase is a function that takes a String and returns a
String.
● Here, T = String, R = String.
🔸 Example_2: Convert List of Strings to List of Lengths (Integer)
List<String> names = Arrays.asList("apple", "banana", "kiwi");
List<Integer> nameLengths = names.stream()
.map(String::length) // Function<String, Integer>
.toList();
IP
}
List<Employee> employees = Arrays.asList(
new Employee("Alice", 30),
ND
new Employee("Bob", 25)
);
List<String> employeeNames =
employees.stream()
.map(Employee::getName) // Function<Employee, String>
.collect(Collectors.toList());
SA
System.out.println(employeeNames); // [Alice, Bob]
🧠 Real-World Use Cases
● Transforming data before saving it to the database.
● Extracting specific fields from complex objects.
● Converting one data structure into another (e.g., DTO mapping).
🔹 3.flatMap()
✦ Purpose: Flattens nested structures/stream into a single stream.
flatMap() is a method in Java's Stream API that:
● Transforms each element in the stream into another stream (or collection).
● Then flattens all those nested streams into a single stream.
● In simple terms: map + flatten = flatMap
🔸 Explanation
● For each element T in the original stream, apply a function that returns a
stream of R, then flatten all those streams into one stream of R."
🧠 Real-time Example:
● Extracting all subjects from multiple student records.
● Reading nested lists from JSON files and flattening them.
● Merging multiple lists of user roles into a single list.
IP
● Imagine a database with two tables: like having RelationShip (OneToMany)
One Departments can have multiple Employees ()or Many Employees belongs to
ND
One Department
i.e
🗃️ Departments Tables 🗃️Employees Tables
id name id name dept_id
1 IT 1 Ram 1
SA
2 HR 2 Shyam 1
3 Seeta 2
🎯 SQL Query (Join with Flattened Result):
● SELECT d.name AS department, e.name AS employee
FROM Departments d
JOIN Employees e ON d.id = e.dept_id;
● This query gives:
department employee
IT Ram
IT Ram
HR Seeta
IP
🔸 Stream + flatMap Example:
List<Department> departments =
ND
new ArrayList<>(Arrays.asList(
new Department("IT",
new ArrayList<>(Arrays.asList(new Employee("Ram"),
new Employee("Shyam")))),
new Department("HR", new ArrayList<>(Arrays.asList(
new Employee("Seeta"))))
));
SA
departments.stream()
.flatMap(dept -> dept.getEmployees().stream())//flatten employee list
.map(Employee::getName) // get names only
.forEach(System.out::println);
🧾 Output:
Ram
Shyam
Seeta
🎨 Visual:
● Before flatMap: [ [Ram, Shyam],[Seeta] ]
● After flatMap: => [Ram, Shyam, Seeta]
● Here, each department has its own list of employees (just like a subquery or
subtable).
● flatMap collects all these sublists into a single flattened stream — similar to
how SQL JOIN combines rows.
Notes By Sandip Vargale
🧠 In Summary:
Concept SQL Java (Stream API)
► When to Use flatMap?
You have a stream of collections (e.g., List<List<String>>).
You want to combine them into a single stream before processing.
🔸 Example 1:
IP
List<List<String>> listOfLists = Arrays.asList(
Arrays.asList("apple", "banana"),
ND
Arrays.asList("cherry", "date")
);
List<String> allItems = listOfLists.stream()
.flatMap(List::stream)
.toList();
System.out.println(allItems); // Output: [apple, banana, cherry, date]
🔸 Example 2:
SA
data.stream()
.flatMap(Collection::stream)
.forEach(System.out::println);
🔸 Example 3:
List<String> sentences = Arrays.asList("hello world", "java streams");
IP
Student student = (Student) o;
return id == student.id && Objects.equals(name, student.name);
}
@Override
ND
public int hashCode() {
return Objects.hash(id, name);
}
}
List<Student> students = Arrays.asList(
new Student(1, "Alice"),
new Student(2, "Bob"),
SA
🔸 Example 1 with integers:
List<Integer> numbers = Arrays.asList(5, 1, 3);
List<Integer> sorted = numbers.stream()
.sorted()
.collect(Collectors.toList());
System.out.println(sorted); // Output: [1, 3, 5]
🔸 Example 2 : Stream<T> sorted(Comparator<? super T> comparator)
This allows you to define a custom sort order using a Comparator.
List<Student> students = Arrays.asList(
new Student(1, "Bob"),
new Student(2, "Alice"),
new Student(3, "Charlie")
);
IP
Sort students by GPA (highest first), then by name (A–Z)
ND
List<Student> students = Arrays.asList(
new Student(1, "Alice", 3.5),
new Student(2, "Bob", 3.9),
new Student(3, "Charlie", 3.9),
new Student(4, "David", 3.2)
);
SA
🧾 Output:
Bob - 3.9
Charlie - 3.9
Alice - 3.5
David - 3.2
🧠 Explanation:
● Comparator.comparingDouble(Student::getGpa).reversed() → sort by GPA descending
● thenComparing(Student::getName) → if GPAs are equal, sort by name ascending
● collect(Collectors.toList()) → collect the sorted stream into a list
Notes By Sandip Vargale
🔸 Example 5: You Can Also Sort By:
.id → Comparator.comparing(Student::getId)
.name length → Comparator.comparingInt(s -> s.getName().length())
🔸 Example 6:
List<String> names = Arrays.asList("John", "Alice", "Bob");
List<String> sortedNames = names.stream()
.sorted()
..toList();
System.out.println(sortedNames); // Output: [Alice, Bob, John]
🔸 Example 7:
Stream.of("banana", "apple", "cherry")
.sorted(Comparator.reverseOrder())
.forEach(System.out::println);
🔹 6.peek()
without modifying the stream.
IP
✦ Purpose: Performs an action on each element as it is consumed from the stream ,
.peek(System.out::println)
.collect(Collectors.toList());
}
}
🔸 Example_2 :
Stream.of("apple", "banana", "cherry")
.peek(System.out::println)
.map(String::toUpperCase)
.forEach(System.out::println);
🔹 8.skip(long n)
✦ Purpose: Skips the first N elements of the stream.
✦ Syntax: Stream<T> skip(long n);
🔸 Example 1 :
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
IP
List<Integer> skipped = numbers.stream()
.skip(3)
.collect(Collectors.toList());
System.out.println(skipped); // Output: [4, 5, 6]
ND
🧠 Real-World Use Case:
● Paginating through a list of records by skipping the first n items.
e.g. Implementing pagination (e.g., page 2 starts after skipping 10 elements).
🔹 9.mapToInt()
types.
✦ Syntax: IntStream mapToInt(ToIntFunction<? super T> mapper);
🔸 Example :
List<String> numbers = Arrays.asList("1", "2", "3");
🔹 11.mapToDouble()
✦ Purpose : Converts elements to a DoubleStream.
✦ Syntax : DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);
🔸 Example:
IP
List<String> numbers = Arrays.asList("1.1", "2.2", "3.3");
double average = numbers.stream()
.mapToDouble(Double::parseDouble)
.sum();
🔹
ND
What are IntStream, LongStream, and DoubleStream?
● They are specialized stream types in Java’s Stream API designed to work
efficiently with primitive data types: int, long, and double, respectively.
🔸 Example:
IntStream intStream = IntStream.of(1, 2, 3, 4);
int sum = intStream.sum(); // 10
THANK YOU
Notes By Sandip Vargale