Skip to main content

Command Palette

Search for a command to run...

Lambda & Stream API in Java 8

Updated
•5 min read•View as Markdown

Collection Framework

How to Learn Java Collections – A Complete Guide | GeeksforGeeks

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

  1. Consumer: Represent an operation that accept single input parameter & does not returns any result
void accept(T t);
  1. Supplier: Represents the supplier of the result, does not accepts any parameter but produces result.
T get();
  1. Function: Represents function that accept one argument process it and produce a result.
R apply(T t);
  1. 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.stream package.

Key Features of Java Streams:

  1. Not a data structure – It doesn’t store elements; it processes them.

  2. Functional – You can use lambda expressions and method references.

  3. Lazy – Operations are not executed until a terminal operation is invoked.

  4. Pipeline processing – Stream operations can be chained into pipelines.

  5. 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:

MethodReturn TypeDescription
forEach(Consumer)voidPerforms an action for each element.
forEachOrdered(Consumer)voidLike forEach but maintains encounter order.
toArray()Object[] / T[]Returns an array containing the elements.
reduce(identity, accumulator)TCombines elements using an accumulator function.
reduce(accumulator)Optional<T>Same as above, but no identity value.
collect(Collector)RPerforms a mutable reduction (e.g., to List, Set).
min(Comparator)Optional<T>Finds minimum element.
max(Comparator)Optional<T>Finds maximum element.
count()longReturns the number of elements.
anyMatch(Predicate)booleanChecks if any element matches condition.
allMatch(Predicate)booleanChecks if all elements match condition.
noneMatch(Predicate)booleanChecks if no elements match condition.
findFirst()Optional<T>Returns the first element (if present).
findAny()Optional<T>Returns any element (may be non-deterministic).