[Go to site: main page, start]

0% found this document useful (0 votes)
10 views28 pages

Java 8 Streams API Overview and Notes

The document provides an overview of Java 8 Streams API, highlighting its purpose to simplify collection processing through functional programming. It covers key concepts such as stream operations, lambda expressions, functional interfaces, and the differences between streams and collections. Additionally, it includes practical examples and interview tips related to streams and their associated functional interfaces.

Uploaded by

S Vasanth
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views28 pages

Java 8 Streams API Overview and Notes

The document provides an overview of Java 8 Streams API, highlighting its purpose to simplify collection processing through functional programming. It covers key concepts such as stream operations, lambda expressions, functional interfaces, and the differences between streams and collections. Additionally, it includes practical examples and interview tips related to streams and their associated functional interfaces.

Uploaded by

S Vasanth
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

🌊 Java 8 Streams API – Simple Revision Notes

🔴 Why Streams were introduced?


Problem before Java 8:
 Collection processing used for / while loops
 Code was long and messy
 Hard to read & maintain
 Parallel processing was difficult
Solution in Java 8:
Streams API was introduced to process collections in a clean, functional, and
readable way.

Feature Description Example

Sequence of elements
Stream supporting functional-style List<Integer> list = ...; [Link]()
operations

Intermediate Return a new stream; lazy filter(), map(), sorted(), distinct()


Operations
Terminal Produce a result or side- forEach(), collect(), count(),
Operations effect; triggers execution reduce()

Parallel Stream Allows parallel processing [Link]()

Utilities to accumulate collect([Link]()), toSet(),


Collectors results joining()

Lazy evaluation, functional stream operations do not modify


Key Points style, no storage original collection
🟢 What is a Stream?
A Stream is a sequence of elements used to process data from a collection
using functional style.
📌 Remember:
 Stream does not store data
 Stream works on collections
 Stream does not change original data

🟢 Programming Style Used


Streams follow:
 ✅ Functional style

 ✅ Declarative style

 ❌ Not imperative (loop-based)


Focus on WHAT to do, not HOW to do.

🔗 Streams depend on these Java 8 features


1. Lambda Expressions
2. Functional Interfaces
3. Method References
4. Collections Framework
🔁 Stream Pipeline (MOST IMPORTANT)
A Stream works in 3 steps:
1⃣ Source
Collection or array
[Link]();

2⃣ Intermediate Operations
 Process data
 Return another Stream
 Lazy execution
Examples:
 filter()
 map()
 sorted()
.filter(n -> n % 2 == 0)

3⃣ Terminal Operation
 Produces result
 Triggers execution
Examples:
 forEach()
 collect()
 count()
.forEach([Link]::println);

🔹 Simple Example (Must Remember)


[Link]()
.filter(n -> n % 2 == 0)
.forEach([Link]::println);
📌 Important Stream Rules (Non-Negotiable)
✅ Rule 1: Stream does NOT store data
Works on existing collection

✅ Rule 2: Stream is ONE-TIME use


Cannot reuse a stream

✅ Rule 3: Stream does NOT modify original data


Original collection remains unchanged

✅ Rule 4: Without terminal operation → NO execution

🟢 Common Stream Methods (Interview Must-Know)


Intermediate Operations
 filter()
 map()
 sorted()
 distinct()
 limit()
Terminal Operations
 forEach()
 collect()
 count()
 reduce()
 findFirst()

📦 Collectors (Very Common)


[Link]()
[Link]()
[Link]()
[Link]()
⚙️ Parallel Streams
[Link]();
Use when:
 Large data
 CPU-intensive tasks

⚠️ Stream vs Collection (Quick Difference)


Stream Collection
Process data Store data
One-time use Reusable
Lazy Eager
Functional style OOP style

🎯 5 One-Line Interview Answers (Memorize)


1⃣ Streams process collections in functional style
2⃣ Streams do not store data
3⃣ Streams are lazy
4⃣ Streams support parallel processing
5⃣ Streams use lambdas and functional interfaces

🟢 Final Memory Formula (Very Easy)


Collection → Stream → filter/map → Result

💡 Final Confidence Note


You now understand:
 WHY Streams exist
 WHAT problem they solved
 HOW they work (basics)
 RULES you must not break
LAMBDA EXPRESSIONS – OVERVIEW
✅ What is a Lambda Expression?
A lambda expression is an anonymous function used to provide an
implementation for a functional interface.
Key points:
 No method name
 No access modifier
 Return type is inferred
 Short & readable
 Introduced in Java 8

🟢 Lambda Syntax
(parameters) -> expression
Examples:
() -> [Link]("Hello");

(a, b) -> a + b;

n -> n % 2 == 0;

⚠️ Lambda Rules (Non-Negotiable)


1️⃣ Works only with functional interfaces
2⃣ Cannot be used with normal interfaces
3️⃣ Return type is inferred by compiler
4️⃣ Body can be single or multiple lines

🔴 Anonymous Class vs Lambda (Quick)


Anonymous Class Lambda
Java 7 Java 8
Too much code Short syntax
Multiple methods One abstract method
Class based Function based

🎯 Lambda One-Line Interview Answer


“A lambda expression is an anonymous function introduced in Java 8 to
simplify anonymous classes.”
🔹 FUNCTIONAL INTERFACES – OVERVIEW
✅ What is a Functional Interface?
An interface that has exactly ONE abstract method.

🟢 Why Functional Interface?


 Lambda needs a target type
 Functional interface provides that contract

👉 Lambda = implementation
👉 Functional Interface = rule

⚠️ Functional Interface Rules (Non-Negotiable)


1️⃣ Only ONE abstract method
2⃣ Can have default methods
3️⃣ Can have static methods
4️⃣ @FunctionalInterface is optional but recommended

🟢 Example
Functional Interface
@FunctionalInterface
interface Greeting {
void sayHello();
}
Lambda Implementation
Greeting g = () -> [Link]("Hello");
[Link]();

📦 Built-in Functional Interfaces (Very Important)


Interface Input Output Used in
Predicate 1️ boolean filter()
Function<T,R> 1️ result map()
Consumer 1️ void forEach()
Supplier 0 result get()
🟢 Easy Memory Trick
Predicate → condition
Function → convert
Consumer → use
Supplier → give

🔗 How Lambda & Functional Interface Work Together


[Link]()
.filter(n -> n > 1️0) // Predicate
.forEach([Link]::println); // Consumer

🎯 Functional Interface Interview One-Line


“A functional interface contains exactly one abstract method and is used as the
target type for lambda expressions.”

🟢 FINAL CLARITY (VERY IMPORTANT)


❌ Lambda is NOT independent
❌ Functional interface is NOT optional
✔ Lambda + Functional Interface always come together

📌 FINAL REVISION FORMULA


Anonymous Class → Problem
Lambda → Short Syntax
Functional Interface → Contract
Streams → Uses Lambda + FI
🌟 Anonymous Class vs Lambda – Complete Overview
Feature Anonymous Class Lambda Expression
A class with no name used for An anonymous function used to
Definition
one-time implementation implement a functional interface
Must have functional interface
Optional. Can be used without
Reference reference to be executed or
reference but cannot reuse
reused
Keyword new keyword required No new keyword
Syntax Verbose Short & concise
✅ Can be reused multiple times
Reuse Only if reference is stored
via reference
Target
Any interface or abstract class Functional interface only
Type
Java
Java 7+ Java 8+
Version
One-time object, quick Cleaner syntax, functional
Use Case
implementation programming, streams
🔹 Key Rules You Must Remember
1️. Anonymous class without reference → can call method once.
2. Lambda → must be assigned to functional interface reference to call
multiple times.
3️. Lambda cannot implement abstract class.
4️. Anonymous class can implement abstract class or interface.
5. Streams always use lambdas internally (functional style).

🔹 Simple Examples Side by Side


Anonymous Class (without reference)
new Runnable() {
@Override
public void run() {
[Link]("Hello from anonymous class");
}
}.run(); // ✅ Works once
Lambda Expression (with reference)
Runnable r = () -> [Link]("Hello from lambda");
[Link](); // ✅ Can reuse
[Link]();

🔹 Interview-Safe One-Liners
1️. “Anonymous class can work without a reference but cannot be reused.”
2. “Lambda expressions must be assigned to a functional interface and can
be reused multiple times.”
3️. “Anonymous class uses new keyword; lambda does not.”
4️. “Lambda can only implement functional interfaces; anonymous class can
implement abstract class or interface.”

🟢 Mental Model
Think of it like this:
Anonymous Class → old style → verbose, one-time use possible
Lambda → new style → functional, short, reusable with reference
Streams → use lambdas to process collections
🔁 Anonymous vs Lambda
✅ What is SAME (70%)
Both:
 Implement one abstract method
 Used for one-time logic
 Mostly used with:
o Runnable
o Comparator
o ActionListener
 Do not create reusable business logic
🟢 Anonymous Class (Java 7)
[Link](list, new Comparator<Employee>() {
@Override
public int compare(Employee e1️, Employee e2) {
return e1️.salary - [Link];
}
});

✂️ Lambda (Java 8)
[Link](list, (e1️, e2) -> e1️.salary - [Link]);
👉 Same logic, fewer lines
👉 That’s it. No magic.

❓ Then WHY did Java introduce Lambda?


Because anonymous classes caused problems:
❌ Problems with Anonymous
 Too much boilerplate
 Hard to read
 Focus on HOW, not WHAT
 Nested code becomes ugly

🆕 What Lambda Gave


 Cleaner code
 Functional style
 Easier to read
 Enables Streams API

🔑 Streams cannot exist without lambda

🟢 Best Interview Line (USE THIS)


“Lambda expressions are a compact replacement for anonymous classes used
with functional interfaces. They reduce boilerplate code but internally work the
same way.
🚀 Real-Time Usage.
Used mainly in:
 Sorting
 Filtering
 Stream pipelines
 Small utility logic

❌ Not for:
 Core business logic
 Large methods
 Complex flows
You are NOT confused now
You just needed clear WHY comparison
🔹 1⃣ Predicate<T>
👉 Used for CONDITIONS (true / false)
Logic
 Takes one input
 Returns boolean
 Used in filtering
Method
boolean test(T t);

Usage
 filter()
 Validation
 Conditions

🟢 Memory: Predicate → Question? ✔ / ❌


🔹 2⃣ Function<T, R>
👉 Used for TRANSFORMATION
Logic
 Takes one input
 Returns one output
Method
R apply(T t);

Usage
 map()
 Conversions
 Data transformation

🟢 Memory: Function → Input ➜ Output


🔹 3⃣ Consumer<T>
👉 Used for DOING ACTION (no return)
Logic
 Takes one input
 Returns nothing
Method
void accept(T t);

Usage
 forEach()
 Printing
 Logging
🟢 Memory: Consumer → Consumes & finishes
🔹 4⃣ Supplier<T>
👉 Used for PROVIDING data
Logic
 Takes no input
 Returns output
Method
T get();

Usage
 Object creation
 Lazy values
 Default values

🟢 Memory: Supplier → Gives data


Streams Method Functional Interface
filter() Predicate
map() Function
forEach() Consumer
generate() Supplier

🎯 Lines:
 Predicate → Condition checking
 Function → Data transformation
 Consumer → Action without return
 Supplier → Provides data
🔹 1⃣ BiPredicate<T, U>
👉 Condition with TWO inputs
Logic
 Takes two inputs
 Returns boolean
 Used for checking conditions
Method
boolean test(T t, U u);

Real-Time Usage
 Validation with two fields
 Comparing two values

🟢 Memory: BiPredicate → 2 inputs → true/false


🔹 2⃣ BiFunction<T, U, R>
👉 Combine two inputs → produce result
Logic
 Takes two inputs
 Returns one result
Method
R apply(T t, U u);

Real-Time Usage
 Calculations
 Combining values
 Mapping two fields to one

🟢 Memory: BiFunction → 2 inputs → 1 output


🔹 3⃣ BiConsumer<T, U>
👉 Perform action on two inputs (no return)
Logic
 Takes two inputs
 Returns nothing
Method
void accept(T t, U u);

Real-Time Usage
Printing
 Logging
 Map iteration

🟢 Memory: BiConsumer → 2 inputs → action


✅ Java Streams – Answers & Examples

🔹 Basic Level (1–15)


1. Create a stream from a list
List<Integer> list = [Link](1️,2,3️);
Stream<Integer> stream = [Link]();
2. Convert a stream back to a list
List<Integer> result = [Link]([Link]());
3. Count elements in a stream
long count = [Link]().count();
4. Filter even numbers
[Link]()
.filter(n -> n % 2 == 0)
.toList();
5. Convert strings to uppercase
[Link]()
.map(String::toUpperCase)
.toList();
6. Sort a list
[Link]().sorted().toList();
7. Limit first 5 elements
[Link]().limit(5).toList();
8. Skip first 3 elements
[Link]().skip(3️).toList();
9. Find first element
Optional<Integer> first = [Link]().findFirst();
10. Check if all match condition
boolean allEven = [Link]().allMatch(n -> n % 2 == 0);
11. Check if any match condition
boolean anyEven = [Link]().anyMatch(n -> n % 2 == 0);
12. Remove duplicates
[Link]().distinct().toList();
13. Collect into Set
Set<Integer> set = [Link]().collect([Link]());
14. Infinite stream of random numbers
[Link](Math::random).limit(5).toList();
15. Create stream from array
[Link](arr);

🔹 Intermediate Level
16. Sum of integers
int sum = [Link]().mapToInt(Integer::intValue).sum();
17. Max & Min
int max = [Link]().max(Integer::compare).get();
int min = [Link]().min(Integer::compare).get();
18. Average
double avg = [Link]().mapToInt(i -> i).average().getAsDouble();
19. Concatenate multiple lists
[Link](list1️.stream(), [Link]()).toList();
20. Group even & odd
Map<Boolean, List<Integer>> map =
[Link]().collect([Link](n -> n % 2 == 0));
21. Group employees by department
[Link]()
.collect([Link](Employee::getDept));
22. Second highest number
[Link]()
.distinct()
.sorted([Link]())
.skip(1️)
.findFirst();
23. Partition >10 and ≤10
[Link](n -> n > 1️0);
24. Word frequency
[Link]()
.collect([Link](w -> w, [Link]()));
25. Remove null values
[Link]().filter(Objects::nonNull).toList();
26. Concatenate strings
[Link]().collect([Link]());
27. Flatten list of lists
[Link]()
.flatMap(List::stream)
.toList();
28. Find duplicate elements
Set<Integer> seen = new HashSet<>();
[Link]().filter(n -> ![Link](n)).toList();
29. Top 3 highest numbers
[Link]()
.sorted([Link]())
.limit(3️)
.toList();
30. String → length map
[Link]()
.collect([Link](s -> s, String::length));
31. Longest word
[Link]()
.max([Link](String::length));
32. Distinct characters
[Link]()
.flatMap(s -> [Link]().mapToObj(c -> (char) c))
.distinct()
.toList();
33. Merge two maps
[Link]((k,v) -> map1️.merge(k, v, Integer::sum));
34. Parallel stream
[Link]().forEach([Link]::println);
35. Summary report
IntSummaryStatistics stats =
[Link]().mapToInt(i -> i).summaryStatistics();

🎯 Important
 Streams are lazy
 Intermediate ops → filter, map, sorted
 Terminal ops → collect, forEach, reduce
 Prefer method references when possible
 Avoid modifying external variables in streams
🔹 Method Reference
A method reference is a shortcut for a lambda expression that calls an existing
method.
Syntax
ClassName::methodName
objectName::methodName
Example
[Link]([Link]::println);
✔️ Shorter
✔️ More readable

🔹 Types of Method Reference


1️⃣ Static Method Reference
Math::max
2⃣ Instance Method Reference
obj::methodName
3️⃣ Instance Method of Arbitrary Object
String::toUpperCase

🔹 Constructor Reference
A constructor reference is used to create objects using a constructor.
It is a special form of method reference.
Syntax
ClassName::new
Example
Supplier<List<String>> s = ArrayList::new;
List<String> list = [Link]();
Parameterized Constructor Example
Function<String, StringBuilder> f = StringBuilder::new;
StringBuilder sb = [Link]("Hello");

🔑 Difference (Easy Table)


Feature Method Reference Constructor Reference
Purpose Call existing method Create object
Symbol ::methodName ::new
Replaces Lambda calling method Lambda using new
🎯 Interview One-Line Answer
Method reference is a shorthand of lambda expression to call an existing
method, while constructor reference is used to create objects.

1️ abstract method → Lambda / Method Reference


2+ abstract methods → NOT allowed

You might also like