Java Streams Intermediate Operations Explained with Examples
The Java Stream API lets you process collections in a fluent, declarative style. In this post, we’ll walk through the most useful intermediate operations with simple examples.
Note: Examples below use Java 8 compatible collect(Collectors.toList()). If you’re on Java 16+, you can replace it with toList().
1) filter() — Select elements by a condition
Keeps only elements that match the predicate.
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
List<Integer> res = list.stream()
.filter(num -> num % 2 != 0) // keep only odd numbers
.collect(Collectors.toList());
System.out.println(res); // [1, 3, 5, 7, 9]
2) map() — Transform each element
Applies a function to every element and returns a stream of results.
List<String> strs = Arrays.asList("rama", "anjaneya", "krishna");
List<String> upper = strs.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(upper); // [RAMA, ANJANEYA, KRISHNA]
3) flatMap() — Flatten nested streams
Useful for List<List<T>> → List<T>.
List<List<String>> groups = Arrays.asList(
Arrays.asList("Hi", "Hello", "How", "are", "you"),
Arrays.asList("This", "is", "water")
);
List<String> flattened = groups.stream()
.flatMap(Collection::stream)
.collect(Collectors.toList());
System.out.println(flattened); // [Hi, Hello, How, are, you, This, is, water]
4) distinct() — Remove duplicates
Returns only unique elements (based on equals()).
List<Integer> nums = Arrays.asList(1,2,2,2,3,3,3,4,4,5,5,6,7,7,8,9,9);
List<Integer> unique = nums.stream()
.distinct()
.collect(Collectors.toList());
System.out.println(unique); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
5) sorted() — Sort elements
Natural order or custom comparator.
// Strings: case-insensitive, descending
List<String> words = Arrays.asList("Aaa", "Aha", "Bee", "Box", "Kit", "Sit", "fit", "Fit");
List<String> sortedWords = words.stream()
.sorted((a, b) -> b.compareToIgnoreCase(a))
.collect(Collectors.toList());
System.out.println(sortedWords);
// Integers: descending
List<Integer> ints = Arrays.asList(1,2,3,5,7,86,4,25,23,3);
List<Integer> sortedDesc = ints.stream()
.sorted((a, b) -> Integer.compare(b, a))
.collect(Collectors.toList());
System.out.println(sortedDesc);
6) limit(n) — Take first n elements
Handy for pagination or previews.
List<Integer> lst = Arrays.asList(1,2,3,5,7,86,4,25,23,3);
List<Integer> firstFive = lst.stream()
.limit(5)
.collect(Collectors.toList());
System.out.println(firstFive); // [1, 2, 3, 5, 7]
7) skip(n) — Skip first n elements
Often used with limit for page offsets.
List<Integer> lst2 = Arrays.asList(10,20,30,40,50,60);
List<Integer> afterThree = lst2.stream()
.skip(3)
.collect(Collectors.toList());
System.out.println(afterThree); // [40, 50, 60]
8) peek() — Inspect elements (debug)
Allows side effects like logging without changing the stream.
List<Integer> base = Arrays.asList(1,2,3,4,5);
List<Integer> doubled = base.stream()
.peek(n -> System.out.println("Processing: " + n))
.map(n -> n * 2)
.collect(Collectors.toList());
System.out.println(doubled);
// Logs "Processing: 1..5", then prints [2, 4, 6, 8, 10]
9) Primitive mappings: mapToInt, mapToLong, mapToDouble
Convert to primitive streams for performance and numeric ops like sum(), average().
List<String> numStrings = Arrays.asList("1", "2", "3", "4");
int sum = numStrings.stream()
.mapToInt(Integer::parseInt)
.sum();
System.out.println(sum); // 10
When to use what?
- filter → keep matching items
- map → transform items
- flatMap → flatten nested lists
- distinct → unique results
- sorted → ordering
- limit/skip → pagination
- peek → logging/debugging
- mapToInt/Long/Double → numeric pipelines
Chain these with terminal ops like collect(), forEach(), reduce() to build expressive pipelines.
Comments
Post a Comment