filter(), map(), collect() — Stream API Core Operations
These three methods form the most common Stream pipeline in Java. Together, they let you select data, transform it, and gather results in a clean, declarative way.
Source → filter → map → collect
1️⃣ filter() — Selection (Intermediate Operation)
What It Does
filter() selects elements that match a condition.
- Accepts a Predicate<T>
- Returns a new Stream
- Does not modify the source
- Lazy (executes only at terminal operation)
Syntax
stream.filter(predicate)
Example
Listnumbers = List.of(10, 15, 20, 25); List evens = numbers.stream() .filter(n -> n % 2 == 0) .toList();
Output: [10, 20]
Key Points
- Used for conditions
- Can chain multiple filter() calls
- Prefer simple predicates
2️⃣ map() — Transformation (Intermediate Operation)
What It Does
map() transforms each element into another form.
- Accepts a Function<T, R>
- One input → one output
- Returns a new Stream
- Does not change original data
Syntax
stream.map(function)
Example
Listnames = List.of("java", "python"); List upper = names.stream() .map(String::toUpperCase) .toList();
Output: ["JAVA", "PYTHON"]
Common Uses
- Object → field
- Type conversion
- Value transformation
list.stream().map(String::length)
3️⃣ collect() — Aggregation (Terminal Operation)
What It Does
collect() converts a stream into a collection or result.
- Accepts a Collector
- Triggers stream execution
- Ends the stream pipeline
Syntax
stream.collect(collector)
Common Collectors
- Collectors.toList()
- Collectors.toSet()
- Collectors.toMap()
- Collectors.joining()
- Collectors.groupingBy()
- Collectors.counting()
Example
Listresult = numbers.stream() .filter(n -> n > 10) .map(n -> n * 2) .collect(Collectors.toList());
Output: [30, 40, 50]
Combined Example (Most Common Pattern)
Listresult = List.of("java", "spring", "api", "docker") .stream() .filter(s -> s.length() > 3) .map(String::toUpperCase) .collect(Collectors.toList());
- Filter → Transform → Collect
- Clean and readable
filter vs map vs collect (Interview Table)
| Method | Type | Purpose |
|---|---|---|
| filter() | Intermediate | Select elements |
| map() | Intermediate | Transform elements |
| collect() | Terminal | Gather results |
map() vs flatMap() (Quick Contrast)
map() → one-to-one
flatMap() → one-to-many (flattens)
List> data = List.of(List.of(1,2), List.of(3,4)); data.stream() .flatMap(List::stream) .toList(); // [1,2,3,4]
Common Beginner Mistakes
- Using forEach() instead of map()
- Expecting filter() to modify original list
- Forgetting collect() (no execution)
- Writing complex logic inside lambdas
- Using map() for side effects
Best Practices
- Use filter → map → collect pattern
- Keep lambdas short and readable
- Prefer method references
- Use collect() for results, not forEach()
- Avoid mutating external variables
Interview-Ready Answers
Short Answer
filter() selects elements, map() transforms elements, and collect() gathers results.
Detailed Answer
In Java Streams, filter() is an intermediate operation used to select elements based on a condition, map() transforms each element into another form, and collect() is a terminal operation that converts the processed stream into a collection or aggregated result using collectors.
Key Takeaway
filter = select
map = transform
collect = gather
This trio is the backbone of Stream API usage and should feel natural and instinctive in modern Java development.
More Examples (filter, map, collect)
1. filter() – Basic Condition
import java.util.*;
class Demo {
public static void main(String[] args) {
Arrays.asList(10, 15, 20, 25)
.stream()
.filter(n -> n > 15)
.forEach(System.out::println);
}
}
Output:
20
25
2. filter() with Strings
Arrays.asList("Java", "API", "Stream")
.stream()
.filter(s -> s.length() > 3)
.forEach(System.out::println);
Output:
Java
Stream
3. Multiple filter() Conditions
Arrays.asList(1, 2, 3, 4, 5, 6)
.stream()
.filter(n -> n % 2 == 0)
.filter(n -> n > 3)
.forEach(System.out::println);
Output:
4
6
4. map() – Transform Values
Arrays.asList(1, 2, 3)
.stream()
.map(n -> n * n)
.forEach(System.out::println);
Output:
1
4
9
5. map() with Strings
Arrays.asList("java", "api")
.stream()
.map(String::toUpperCase)
.forEach(System.out::println);
Output:
JAVA
API
6. filter() + map() Together (Very Common)
Arrays.asList(1, 2, 3, 4, 5)
.stream()
.filter(n -> n % 2 == 0)
.map(n -> n * 10)
.forEach(System.out::println);
Output:
20
40
7. Mapping Objects to Fields
class User {
int age;
User(int age) { this.age = age; }
}
List users = List.of(new User(20), new User(30));
users.stream()
.map(u -> u.age)
.forEach(System.out::println);
8. filter() on Objects
users.stream()
.filter(u -> u.age > 25)
.forEach(u -> System.out.println(u.age));
9. collect() → List
import java.util.stream.*; Listevens = Arrays.asList(1, 2, 3, 4) .stream() .filter(n -> n % 2 == 0) .collect(Collectors.toList()); System.out.println(evens);
Output:
[2, 4]
10. collect() → Set
Setset = Arrays.asList(1, 1, 2, 2, 3) .stream() .collect(Collectors.toSet()); System.out.println(set);
11. collect() → Map
Mapmap = Arrays.asList("Java", "API") .stream() .collect(Collectors.toMap( String::length, s -> s )); System.out.println(map);
12. filter() + collect() → Count via List
long count =
Arrays.asList(1, 2, 3, 4)
.stream()
.filter(n -> n > 2)
.collect(Collectors.toList())
.size();
System.out.println(count);
13. Better Way: filter() + count()
long count =
Arrays.asList(1, 2, 3, 4)
.stream()
.filter(n -> n > 2)
.count();
System.out.println(count);
14. map() to Primitive Stream (mapToInt)
int totalLength =
Arrays.asList("Java", "Stream")
.stream()
.mapToInt(String::length)
.sum();
System.out.println(totalLength);
15. collect() with joining()
import java.util.stream.*;
String result =
Arrays.asList("Java", "Stream", "API")
.stream()
.collect(Collectors.joining(", "));
System.out.println(result);
Output:
Java, Stream, API
16. collect() with groupingBy()
Map> grouped = Arrays.asList("a", "bb", "ccc") .stream() .collect(Collectors.groupingBy(String::length)); System.out.println(grouped);
17. collect() with partitioningBy()
Map> parts = Arrays.asList(1, 2, 3, 4) .stream() .collect(Collectors.partitioningBy(n -> n % 2 == 0)); System.out.println(parts);
18. filter() Removes Nulls (Interview Favorite)
Arrays.asList("Java", null, "API")
.stream()
.filter(Objects::nonNull)
.forEach(System.out::println);
19. map() vs forEach() (Common Trap)
// ❌ does NOT modify elements
list.forEach(s -> s.toUpperCase());
// ✅ correct
list.stream()
.map(String::toUpperCase)
.forEach(System.out::println);
20. Order of Operations Matters
Arrays.asList(1, 2, 3)
.stream()
.map(n -> n * 2)
.filter(n -> n > 3)
.forEach(System.out::println);
Output:
4
6
21. Laziness Demonstration
Arrays.asList(1, 2, 3)
.stream()
.filter(n -> {
System.out.println("filter " + n);
return n > 1;
});
// ❌ no output (no terminal operation)
22. Reusing Stream (Illegal)
Streams = Arrays.asList(1, 2).stream(); s.forEach(System.out::println); // s.filter(x -> x > 1); // ❌ IllegalStateException
23. filter() + map() + collect() (Real Pattern)
Listresult = Arrays.asList("java", "api", "stream") .stream() .filter(s -> s.length() > 3) .map(String::toUpperCase) .collect(Collectors.toList()); System.out.println(result);
24. Parallel Stream Caution
Arrays.asList(1, 2, 3, 4)
.parallelStream()
.map(n -> n * 2)
.forEach(System.out::println);
Note: Order not guaranteed.
25. Interview Summary – Core Stream Ops
filter() → select
map() → transform
collect() → accumulate
Key Points:
- filter() → Predicate
- map() → Function
- collect() → Collector
- Streams are lazy
- Order: source → intermediate → terminal