Lambda & Stream API in Java 8
Collection Framework

The Java Collection Framework is a set of classes and interfaces in Java that provides built-in data structures and algorithms for storing, manipulating, and retrieving groups of objects efficiently.
Functional Interface
- If the interface contains only 1 abstract method it is knows as functional interface.
Types of Functional Interface
- Consumer: Represent an operation that accept single input parameter & does not returns any result
void accept(T t);
- Supplier: Represents the supplier of the result, does not accepts any parameter but produces result.
T get();
- Function: Represents function that accept one argument process it and produce a result.
R apply(T t);
- Predicate: Represent function that accept one argument & return boolean.
boolean test(T t)
Lambda Expression
Lambda expression is a way to implement functional interface.
We can implement functional interface by implementing interface, by anonymous class & by lambda expressions.
public class Main {
public static void main(String[] args) {
// Consumer
Consumer<String> consumer = (String s) -> {
System.out.println(s);
};
consumer.accept("hello from consumer");
// Supplier
Supplier<String> supplier = () -> "hello from Supplier";
String msg = supplier.get();
System.out.println(msg);
// Function
Function<Integer, String> function = String::valueOf;
String num = function.apply(69);
System.out.println("Number converted to string : " + num);
// Predicate
Predicate<Integer> predicate = (Integer i) -> i % 2 == 0;
System.out.println("Even " + predicate.test(10));
}
}
Stream API
- In Java, a Stream is a sequence of elements that supports functional-style operations to process data. Streams are introduced in Java 8 as part of the
java.util.streampackage.
Key Features of Java Streams:
Not a data structure – It doesn’t store elements; it processes them.
Functional – You can use lambda expressions and method references.
Lazy – Operations are not executed until a terminal operation is invoked.
Pipeline processing – Stream operations can be chained into pipelines.
Can be parallelized – Streams can easily be made parallel to leverage multi-core processors.
Common Stream Operations
1. Creating a Stream
javaCopyEditList<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();
2. Intermediate Operations (these return a new stream)
filter()map()sorted()distinct()
3. Terminal Operations (these produce a result or side-effect)
collect()forEach()count()reduce()anyMatch(),allMatch()
Examples:
public class Main {
public void waysToCreateStream() {
// method 1
List<Integer> list = List.of(1, 2, 3, 4, 5);
Stream<Integer> stream1 = list.stream();
// method 2
Integer[] nums = {1, 2, 3};
Stream<Integer> stream2 = Arrays.stream(nums);
// method 3
Stream<Integer> stream3 = Stream.of(nums);
// method 4
Stream.Builder<Integer> streamBuilder = Stream.builder();
streamBuilder.add(10);
streamBuilder.add(20);
Stream<Integer> stream4 = streamBuilder.build();
}
public static void streamIntermediateMethods() {
/*
filter method
*/
List<String> words = List.of("HI", "WORLD", "MY", "NAME", "IS", "HARSH");
long count = words.stream()
.filter((String word) -> word.length() > 2)
.count();
System.out.println("Words greater than count 2 -> " + count);
/*
Function : <R> Stream<R> map(Function<? super T, ? extends R> mapper)
Description: The **map()** method in Java Streams is an intermediate operation that
transforms each element of the stream using a function.
*/
List<String> lowerCaseWords = words.stream()
.map((String word) -> word.toLowerCase())
.collect(Collectors.toList());
System.out.println("Lowercase words " + lowerCaseWords);
/*
Function: flatMap
Description: **flatMap()** method in Java Streams is like a combination of map() and flatten().
It is used when each element of the stream is mapped to a stream itself, and
you want to flatten the resulting nested structure into a single stream.
*/
List<List<Integer>> _2dList = Arrays.asList(
Arrays.asList(1,2,3),
Arrays.asList(4,5,6),
Arrays.asList(7,8,9)
);
List<Integer> list = _2dList.stream()
.flatMap((List<Integer> currentList) -> currentList.stream())
.collect(Collectors.toList());
System.out.println("Flatmap List " + list);
/*
Arrays.stream()
*/
Integer[] arr = {3, 4, 2, 1, 6, 3};
Stream<Integer> streamArray = Arrays.stream(arr);
/*
Function: peek()
Description: helps you to see intermediate result of the stream which is getting passed
*/
list.stream()
.map((Integer num) -> num * -1)
.peek((Integer num) -> System.out.println("Peek num " + num))
.limit(2)
.collect(Collectors.toList());
/*
limit: limits the record by given count
skip: skips the starting record by given count
*/
/*
Function: mapToInt
Description: The **mapToInt()** method in Java Streams is a specialized map operation
that is used when you want to convert elements of a stream to primitive
int values.
*/
int[] array1 = list.stream()
.mapToInt(num -> num)
.toArray();
System.out.println("mapToInt Array " + Arrays.toString(array1));
/*
Function: min
Description: Returns the first element from list
*/
Optional<Integer> minElement = list.stream()
.min((Integer num1, Integer num2) -> num2 - num1);
System.out.println("Min element " + minElement.get());
/*
Function: max
Description: Returns the last element from list
*/
Optional<Integer> maxElement = list.stream()
.min((Integer num1, Integer num2) -> num2 - num1);
System.out.println("Min element " + maxElement.get());
Map<Integer, Integer> map = new HashMap<>();
map.put(10, 1);
map.put(1, 1);
Map<Integer, Integer> sortedMap = map.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue
));
}
public static void main(String[] args) {
streamIntermediateMethods();
}
}
Terminal Operations in Java Streams:
| Method | Return Type | Description |
forEach(Consumer) | void | Performs an action for each element. |
forEachOrdered(Consumer) | void | Like forEach but maintains encounter order. |
toArray() | Object[] / T[] | Returns an array containing the elements. |
reduce(identity, accumulator) | T | Combines elements using an accumulator function. |
reduce(accumulator) | Optional<T> | Same as above, but no identity value. |
collect(Collector) | R | Performs a mutable reduction (e.g., to List, Set). |
min(Comparator) | Optional<T> | Finds minimum element. |
max(Comparator) | Optional<T> | Finds maximum element. |
count() | long | Returns the number of elements. |
anyMatch(Predicate) | boolean | Checks if any element matches condition. |
allMatch(Predicate) | boolean | Checks if all elements match condition. |
noneMatch(Predicate) | boolean | Checks if no elements match condition. |
findFirst() | Optional<T> | Returns the first element (if present). |
findAny() | Optional<T> | Returns any element (may be non-deterministic). |