© 2024 Java Streams Tutorial. All rights reserved.
Java Streams were introduced in Java 8 as part of the java.util.stream
package. They revolutionized data processing in Java by enabling functional-style operations on collections, such as filtering, mapping, and reducing, in a declarative and concise manner. Streams allow you to process data in a pipeline, making code more readable and expressive.
- 🔄 Functional Programming: Streams bring functional programming concepts (like map, filter, reduce) to Java, allowing you to write more declarative code.
- 📝 Conciseness: Stream operations are often more concise than traditional loops.
- 👁️ Readability: Stream pipelines clearly express the intent of data transformations.
- ⚡ Parallel Processing: Streams can be easily parallelized for multicore performance gains.
- 🔗 Chaining: Multiple operations can be chained together in a single pipeline.
- 🚫 One-time Use: Streams cannot be reused after a terminal operation.
- 🐛 Debugging Difficulty: Stream pipelines can be harder to debug than imperative code.
- 📊 Performance: In some cases, especially with small collections or simple operations, traditional loops may outperform streams.
- 🔄 Stateful/Imperative Logic: Streams are not ideal for deeply imperative or stateful logic.
- 💥 Side Effects: Streams are designed for stateless operations; using side effects can lead to bugs.
- ✅ When you need to transform, filter, or aggregate data in collections.
- ✅ For readable, declarative data processing pipelines.
- ✅ When you want to leverage parallel processing easily.
- ❌ In performance-critical code where micro-optimization is required.
- ❌ When you need to reuse the same data pipeline multiple times.
- ❌ For deeply imperative, stateful, or side-effect-heavy logic.
- ❌ When debugging complex logic is a priority.
Stream operations are divided into two main types:
- Transform the stream (return another stream)
- Lazy (executed only when a terminal operation is invoked)
- Examples:
map
,filter
,sorted
,distinct
,flatMap
,peek
,limit
,skip
- Trigger processing and produce a result or side effect
- Close the stream (cannot be reused)
- Examples:
collect
,reduce
,forEach
,count
,min
,max
,anyMatch
,allMatch
,noneMatch
,findFirst
,findAny
,toArray
- Each row shows a sample problem, input, output, and the function name.
- The function is implemented in the corresponding Example class (linked in the Function Name column).
- The "Sample Problem" column matches the full practice problem name as listed in the Example class's comment section.
- Click the Example class link to see the full code and all related methods.
Method | Input Stream | Output Stream | Use Case | When to Use |
---|---|---|---|---|
map() |
Stream<T> |
Stream<R> |
Generic transformation | Transform each element independently |
flatMap() |
Stream<T> |
Stream<R> |
Flatten nested collections | When you have nested structures to flatten |
mapToInt() |
Stream<T> |
IntStream |
Convert to primitive int | Better performance for int operations |
mapToLong() |
Stream<T> |
LongStream |
Convert to primitive long | Handle large numbers without overflow |
mapToDouble() |
Stream<T> |
DoubleStream |
Convert to primitive double | Mathematical operations with decimals |
mapToObj() |
IntStream, etc. |
Stream<T> |
Convert primitive to object | Chain primitive and object operations |
Use Map() When: | Use Reduce() When: |
---|---|
✅ Transform each element independently | ✅ Combine all elements into a single result |
✅ Need 1:1 mapping (one input → one output) | ✅ Need aggregation (sum, product, concatenation) |
✅ Extract properties or apply functions | ✅ Find min/max values |
✅ Change data types | ✅ Build complex objects from multiple elements |
✅ Maintain the same number of elements | ✅ Reduce collection to a single value |
✅ Apply same operation to each element | ✅ Accumulate state across elements |
🔍 Key Differences:
- Map():
[1,2,3] → [2,4,6]
(transform each) - Reduce():
[1,2,3] → 6
(combine all)
💡 Internal Working:
- Map(): Each element processed independently, lazy evaluation, easily parallelizable
- Reduce(): Elements combined sequentially, requires accumulator, harder to parallelize
- Using
reduce()
to transform each element (wrong!) - Using
map()
to combine all elements (wrong!) - Using
reduce()
when you need to maintain element count - Using
map()
when you need a single aggregated result
Sample Problem (as in Example class) | Input | Output | Function Name |
---|---|---|---|
Convert a list of integers to their squares | [1, 2, 3, 4, 5] |
[1, 4, 9, 16, 25] |
squareIntegers() |
Convert a list of strings to uppercase | ["apple", "banana", "cherry"] |
["APPLE", "BANANA", "CHERRY"] |
toUpperCase() |
Given a list of Employee objects, extract their names | [Alice(30, HR, $60000), Bob(25, Engineering, $80000)] |
["Alice", "Bob"] |
extractEmployeeNames() |
Add 10 to each element in a list | [1, 2, 3, 4, 5] |
[11, 12, 13, 14, 15] |
addTen() |
Convert a list of strings to their lengths | ["apple", "banana", "cherry"] |
[5, 6, 6] |
stringLengths() |
Advanced: Map Employee list to salary bands (e.g., "Low", "Medium", "High") | [Alice($60000), Bob($80000), Diana($90000)] |
["Low", "Medium", "High"] |
employeeSalaryBands() |
Advanced: Map Employee list to name-department pairs (e.g., "Alice-HR") | [Alice(HR), Bob(Engineering)] |
["Alice-HR", "Bob-Engineering"] |
employeeNameDepartmentPairs() |
Sample Problem (as in Example class) | Input | Output | Function Name |
---|---|---|---|
Flatten a list of lists of integers | [[1,2,3], [4,5], [6,7,8]] |
[1, 2, 3, 4, 5, 6, 7, 8] |
flattenListOfLists() |
Split a list of sentences into words | ["Hello world", "Java streams"] |
["Hello", "world", "Java", "streams"] |
splitSentencesToWords() |
Advanced: Flatten a list of Employee objects, each with a list of skills, into a list of skills | [Alice([Java,Spring]), Bob([Java,React])] |
[Java, Spring, Java, React] |
flattenEmployeeSkills() |
Advanced: Given a list of paragraphs (list of sentences), return a list of all unique words | [["Java is great", "Streams are cool"], ["Practice Java streams"]] |
["java", "is", "great", "streams", "are", "cool", "practice"] |
uniqueWordsFromParagraphs() |
Sample Problem (as in Example class) | Input | Output | Function Name |
---|---|---|---|
mapToInt(): Convert strings to int stream for better performance | ["apple", "banana", "cherry"] |
[5, 6, 6] |
mapToIntExample() |
mapToLong(): Convert integers to long stream for large numbers | [1, 2, 3, 4, 5] |
[1, 4, 9, 16, 25] |
mapToLongExample() |
mapToDouble(): Convert integers to double stream for mathematical operations | [1, 4, 9, 16, 25] |
[1.0, 2.0, 3.0, 4.0, 5.0] |
mapToDoubleExample() |
mapToObj(): Chain primitive and object operations | ["apple", "banana", "cherry"] |
["Length: 5", "Length: 6", "Length: 6"] |
mapToObjExample() |
Sample Problem (as in Example class) | Input | Output | Function Name |
---|---|---|---|
Chaining: Multiple map operations in sequence | [Alice, Bob, Charlie] |
["Employee: ALICE", "Employee: BOB", "Employee: CHARLIE"] |
chainingMapOperations() |
Performance: Map() vs Reduce() comparison for transformations | [1, 2, 3, 4, 5] |
map(): [2, 4, 6, 8, 10] vs reduce(): 30 |
mapVsReduceComparison() |
Parallel: Parallel stream mapping for performance | [1, 2, 3, 4, 5] |
[1, 4, 9, 16, 25] |
parallelMapExample() |
Comprehensive: All map types in one example | [Employees with skills] |
[Various transformations] |
comprehensiveMapExample() |
Sample Problem (as in Example class) | Input | Output | Function Name |
---|---|---|---|
Filter even numbers from a list | [1, 2, 3, 4, 5, 6] |
[2, 4, 6] |
filterEvenNumbers() |
Filter strings that start with a specific letter | ["apple", "banana", "cherry", "avocado"] |
["apple", "avocado"] |
filterByStartingLetter() |
Filter employees with salary > 50,000 | [Alice($60000), Bob($80000), Charlie($75000)] |
[Bob($80000), Charlie($75000)] |
filterHighSalaryEmployees() |
Remove null or empty strings from a list | ["apple", "", null, "banana"] |
["apple", "banana"] |
removeNullOrEmpty() |
Advanced: Filter prime numbers from a list | [1, 2, 3, 4, 5, 11, 13, 17, 20] |
[2, 3, 5, 11, 13, 17] |
filterPrimes() |
Advanced: Filter employees in a specific department and above a certain age | [Alice(HR), Bob(Engineering), Charlie(Engineering)] |
[Bob(Engineering), Charlie(Engineering)] |
filterEmployeesByDeptAndAge() |
Custom: Filter employees whose name starts with a given letter | [Alice, Bob, Charlie] |
[Alice] |
filterEmployeesByNameStart() |
Custom: Filter employees in a salary band (e.g., Medium) | [Alice($60000), Bob($80000), Diana($90000)] |
[Bob($80000)] |
filterEmployeesBySalaryBand() |
Custom: Filter employees with age between 25 and 35 and in Engineering | [Alice(30,HR), Bob(25,Engineering), Charlie(28,Engineering)] |
[Bob(25,Engineering), Charlie(28,Engineering)] |
filterEmployeesByAgeAndDept() |
Sample Problem (as in Example class) | Input | Output | Function Name |
---|---|---|---|
Sort a list of integers in ascending order | [5, 2, 8, 1, 3] |
[1, 2, 3, 5, 8] |
sortIntegers() |
Sort a list of strings alphabetically | ["banana", "apple", "cherry"] |
["apple", "banana", "cherry"] |
sortStrings() |
Sort employees by age | [Alice(30), Bob(25), Charlie(28)] |
[Bob(25), Charlie(28), Alice(30)] |
sortEmployeesByAge() |
Sort a list in reverse order | [1, 2, 3, 4, 5] |
[5, 4, 3, 2, 1] |
sortIntegersDescending() |
Advanced: Sort employees by department, then by salary descending | [Alice(HR,$60k), Bob(Eng,$80k), Charlie(Eng,$75k)] |
[Charlie(Eng,$75k), Bob(Eng,$80k), Alice(HR,$60k)] |
sortEmployeesByDeptAndSalary() |
Custom: Sort employees by name alphabetically | [Alice, Bob, Charlie] |
[Alice, Bob, Charlie] |
sortEmployeesByName() |
Custom: Sort employees by salary ascending | [Alice($60k), Bob($80k), Charlie($75k)] |
[Alice($60k), Charlie($75k), Bob($80k)] |
sortEmployeesBySalary() |
Custom: Sort employees by age, then by name | [Alice(30), Bob(25), Charlie(28)] |
[Bob(25), Charlie(28), Alice(30)] |
sortEmployeesByAgeThenName() |
Sample Problem (as in Example class) | Input | Output | Function Name |
---|---|---|---|
Remove duplicates from a list of integers | [1, 2, 2, 3, 4, 4, 5] |
[1, 2, 3, 4, 5] |
removeDuplicates() |
Remove duplicate strings (case-insensitive) | ["Apple", "Banana", "apple", "banana"] |
["Apple", "Banana"] |
removeDuplicateStringsIgnoreCase() |
Advanced: Remove duplicate Employee objects based on employee ID | [Alice(ID:1), Bob(ID:2), Charlie(ID:1)] |
[Alice(ID:1), Bob(ID:2)] |
removeDuplicateEmployeesById() |
Custom: Remove duplicate Employee objects based on name | [Alice(ID:1), Bob(ID:2), Alice(ID:3)] |
[Alice(ID:1), Bob(ID:2)] |
removeDuplicateEmployeesByName() |
Custom: Remove duplicate Employee objects based on both name and id | [Alice(ID:1), Bob(ID:2), Alice(ID:1)] |
[Alice(ID:1), Bob(ID:2)] |
removeDuplicateEmployeesByNameAndId() |
Sample Problem (as in Example class) | Input | Output | Function Name |
---|---|---|---|
Flatten a list of lists of integers | [[1,2,3], [4,5], [6,7,8]] |
[1, 2, 3, 4, 5, 6, 7, 8] |
flattenListOfLists() |
Split a list of sentences into words | ["Hello world", "Java streams"] |
["Hello", "world", "Java", "streams"] |
splitSentencesToWords() |
Advanced: Flatten a list of Employee objects, each with a list of skills, into a list of skills | [Alice([Java,Spring]), Bob([Java,React])] |
[Java, Spring, Java, React] |
flattenEmployeeSkills() |
Advanced: Given a list of paragraphs (list of sentences), return a list of all unique words | [["Java is great", "Streams are cool"], ["Practice Java streams"]] |
["java", "is", "great", "streams", "are", "cool", "practice"] |
uniqueWordsFromParagraphs() |
Custom: Flatten all project names from a list of Employee objects | [Alice([Payroll,Recruitment]), Bob([Inventory,Payroll])] |
[Payroll, Recruitment, Inventory] |
flattenEmployeeProjects() |
Custom: Flatten all unique characters from a list of Employee names | [Alice, Bob] |
[A, l, i, c, e, B, o, b] |
flattenEmployeeNameCharacters() |
Sample Problem (as in Example class) | Input | Output | Function Name |
---|---|---|---|
Log each element as it passes through the stream | [1, 2, 3, 4, 5] |
Peek: 1, Peek: 2, ... + [2, 4, 6, 8, 10] |
logElements() |
Debug transformations in a stream pipeline | ["apple", "banana"] |
Original: apple, Uppercased: APPLE, ... + [APPLE, BANANA] |
debugPipeline() |
Advanced: Use peek to collect elements into a side list for auditing | [1, 2, 3] |
[2, 3, 4] + Audit trail: [1, 2, 3] |
auditElements() |
Custom: Use peek to count how many elements pass a certain stage | [1, 2, 3, 4, 5] |
[2, 4] + Count of evens: 2 |
countPassingElements() |
Sample Problem (as in Example class) | Input | Output | Function Name |
---|---|---|---|
Get the first 3 elements of a list using limit | [1, 2, 3, 4, 5, 6, 7] |
[1, 2, 3] |
firstThree() |
Skip the first 2 elements and process the rest | ["apple", "banana", "cherry", "date"] |
["cherry", "date"] |
skipTwo() |
Advanced: Paginate a list using skip and limit | [1, 2, 3, 4, 5, 6, 7] |
[4, 5, 6] |
paginate() |
Custom: Get the top 2 highest paid employees | [Alice($60k), Bob($80k), Charlie($75k), Diana($90k)] |
[Diana($90k), Bob($80k)] |
topTwoHighestPaid() |
Custom: Skip the first employee in each department (grouped by department) | [Alice(HR), Bob(Eng), Charlie(Eng), Diana(Finance)] |
[Charlie(Eng), Diana(Finance)] |
skipFirstInEachDepartment() |
Sample Problem (as in Example class) | Input | Output | Function Name |
---|---|---|---|
Collect a list of integers into a Set | [1, 2, 3, 4, 5, 6, 7, 8] |
{1, 2, 3, 4, 5, 6, 7, 8} |
collectToSet() |
Collect a list of strings into a single concatenated string | ["apple", "banana", "cherry", "date"] |
"apple, banana, cherry, date" |
concatenateStrings() |
Partition a list of numbers into even and odd | [1, 2, 3, 4, 5, 6, 7, 8] |
{false=[1,3,5,7], true=[2,4,6,8]} |
partitionEvenOdd() |
Group a list of strings by their length | ["apple", "banana", "cherry", "date"] |
{4=[date], 5=[apple], 6=[banana, cherry]} |
groupByLength() |
Advanced: Group a list of Employee objects by department | [Alice(HR), Bob(Eng), Charlie(Eng), Diana(Finance)] |
{HR=[Alice], Engineering=[Bob,Charlie], Finance=[Diana]} |
groupEmployeesByDepartment() |
Advanced: Partition employees by salary > 75000 | [Alice($60k), Bob($80k), Charlie($75k), Diana($90k)] |
{false=[Alice,Charlie], true=[Bob,Diana]} |
partitionEmployeesBySalary() |
Sample Problem (as in Example class) | Input | Output | Function Name |
---|---|---|---|
Sum all numbers in a list | [1, 2, 3, 4, 5] |
15 |
sumNumbers() |
Find the maximum value in a list | [1, 2, 3, 4, 5] |
5 |
findMax() |
Concatenate all strings in a list | ["apple", "banana", "cherry"] |
"applebananacherry" |
concatenateStrings() |
Advanced: Find the product of all numbers in a list | [1, 2, 3, 4, 5] |
120 |
productNumbers() |
Advanced: Find the employee with the highest salary | [Alice($60k), Bob($80k), Charlie($75k)] |
Bob ($80k) |
employeeWithHighestSalary() |
Sample Problem (as in Example class) | Input | Output | Function Name |
---|---|---|---|
Find the minimum value in a list | [5, 2, 8, 1, 3] |
1 |
findMin() |
Find the maximum value in a list | [5, 2, 8, 1, 3] |
8 |
findMax() |
Find the employee with the highest salary | [Alice($60k), Bob($80k), Charlie($75k)] |
Bob ($80k) |
employeeWithHighestSalary() |
Custom: Find the employee with the lowest age | [Alice(30), Bob(25), Charlie(28)] |
Bob (25) |
employeeWithLowestAge() |
Custom: Find the string with the maximum length | ["banana", "apple", "cherry", "date"] |
"banana" |
stringWithMaxLength() |
Sample Problem (as in Example class) | Input | Output | Function Name |
---|---|---|---|
Count the number of elements in a list | [1, 2, 3, 4, 5, 6, 7] |
7 |
countElements() |
Count the number of strings longer than 5 characters | ["apple", "banana", "cherry", "date", "elderberry"] |
3 |
countLongStrings() |
Custom: Count the number of employees in Engineering | [Alice(HR), Bob(Eng), Charlie(Eng), Diana(Finance)] |
2 |
countEngineeringEmployees() |
Custom: Count the number of employees with salary > 75000 | [Alice($60k), Bob($80k), Charlie($75k), Diana($90k)] |
3 |
countHighSalaryEmployees() |
Custom: Count the number of unique departments | [Alice(HR), Bob(Eng), Charlie(Eng), Diana(Finance)] |
3 |
countUniqueDepartments() |
Sample Problem (as in Example class) | Input | Output | Function Name |
---|---|---|---|
Print each element in a list | [1, 2, 3, 4, 5] |
Element: 1, Element: 2, ... |
printElements() |
Print each employee's name and salary | [Alice($60k), Bob($80k)] |
Alice: $60000, Bob: $80000 |
printEmployeeNameSalary() |
Advanced: Print all strings in reverse order | ["apple", "banana", "cherry", "date"] |
Reverse: date, Reverse: cherry, ... |
printReverse() |
Custom: Print all employees in a specific department | [Alice(HR), Bob(Eng), Charlie(Eng)] |
Bob (Engineering), Charlie (Engineering) |
printEmployeesInDepartment() |
Custom: Print all employees with salary above a threshold | [Alice($60k), Bob($80k), Charlie($75k)] |
Bob ($80k), Charlie ($75k) |
printHighSalaryEmployees() |
Sample Problem (as in Example class) | Input | Output | Function Name |
---|---|---|---|
Check if any number in a list is even (anyMatch) | [1, 3, 5, 7, 8] |
true |
anyEven() |
Check if all strings are non-empty (allMatch) | ["Apple", "Banana", "", "Avocado"] |
false |
allNonEmpty() |
Check if no employee is under 18 (noneMatch) | [Alice(30), Bob(25), Charlie(28)] |
true |
noneUnder18() |
Find the first string that starts with 'A' (findFirst) | ["Apple", "Banana", "Avocado"] |
"Apple" |
findFirstA() |
Find any employee in Engineering (findAny) | [Alice(HR), Bob(Engineering), Charlie(Engineering)] |
Bob (Engineering) |
findAnyEngineering() |
Custom: Check if all employees in a department have salary > 70000 | [Alice($60k), Bob($80k), Charlie($75k)] |
false |
allSalaryAbove() |
Custom: Find the first employee with salary > 80000 | [Alice($60k), Bob($80k), Charlie($75k)] |
Bob ($80k) |
findFirstSalaryAbove() |
Sample Problem (as in Example class) | Input | Output | Function Name |
---|---|---|---|
Convert a list of integers to an Integer array | [1, 2, 3, 4, 5] |
[1, 2, 3, 4, 5] |
toIntegerArray() |
Convert a list of strings to a String array | ["apple", "banana", "cherry"] |
["apple", "banana", "cherry"] |
toStringArray() |
Advanced: Convert a list of Employee objects to an Employee array | [Alice(30,HR,$60k), Bob(25,Eng,$80k)] |
[Alice(30,HR,$60k), Bob(25,Eng,$80k)] |
toEmployeeArray() |
Custom: Convert a stream of uppercase strings to an array | ["apple", "banana", "cherry"] |
["APPLE", "BANANA", "CHERRY"] |
uppercaseToArray() |
Each example class in this project:
- 🎯 Focuses on a specific stream operation
- 📝 Begins with a detailed comment section listing practice problems (from basic to advanced/interview level, including custom object scenarios)
- 🔧 Contains methods that solve each problem, printing both the input and output to visualize the transformation
- 🚀 Includes a
main
method with sample input to demonstrate all examples
Operation | Class | Practice Problems |
---|---|---|
Map | Map_Example.java |
Transform data, extract properties, convert types, create derived values |
Filter | Filter_Example.java |
Filter by conditions, remove nulls, find primes, complex filtering |
Sorted | Sorted_Example.java |
Sort by single/multiple fields, reverse order, custom comparators |
Distinct | Distinct_Example.java |
Remove duplicates, case-insensitive distinct, custom deduplication |
FlatMap | FlatMap_Example.java |
Flatten nested structures, split strings, extract collections |
Peek | Peek_Example.java |
Debug pipelines, audit elements, count passing elements |
Limit/Skip | LimitSkip_Example.java |
Pagination, top N elements, skip elements, windowing |
Operation | Class | Practice Problems |
---|---|---|
Collect | Collect_Example.java |
Group by, partition, collect to different collections, join strings |
Reduce | Reduce_Example.java |
Sum, product, concatenate, find max/min, custom reduction |
Min/Max | MinMax_Example.java |
Find minimum/maximum values, custom comparators |
Count | Count_Example.java |
Count elements, count by conditions, count unique values |
ForEach | ForEach_Example.java |
Print elements, perform side effects, iterate with actions |
Match/Find | MatchFind_Example.java |
anyMatch, allMatch, noneMatch, findFirst, findAny |
ToArray | ToArray_Example.java |
Convert streams to arrays of different types |
© 2024 Java Streams Tutorial. All rights reserved.
This repository and all its contents are protected by copyright law and international treaties. Unauthorized reproduction, distribution, or copying of this content may result in severe civil and criminal penalties, and will be prosecuted to the maximum extent possible under the law.
✅ Proper Usage: Fork this repository and give proper attribution
❌ Prohibited: Direct copying without permission or attribution
For licensing inquiries: Contact the copyright holder
We'd love your help to make this Java Streams tutorial even better! Here's how you can contribute:
- Found a bug in the examples?
- Spotted an error in the documentation?
- Have a suggestion for improvement?
- → Raise an Issue
- Add new stream operation examples
- Improve existing examples with better use cases
- Add more advanced interview-level problems
- → Submit a Pull Request
- Improve explanations and comments
- Add more practice problems
- Suggest better formatting or organization
- → Fork and Contribute
Every contribution, no matter how small, helps make this tutorial better for the entire Java community. Thank you for your support! 🚀
Thank you for respecting intellectual property rights! 🙏