Java Stream Operations -Part 2

6 min read

In continuation with the previous blog post, we will be learning more operations with respect to Stream API.

Note: We will be using same data seeding classes used in the previous post.

Stream API – reduce()

Reduce is a terminal operation, used to reduce multiple contents of a stream to a single value. It takes two parameters as input.

  1. First Parameter: Default or initial value.
  2. Second Parameter: BinaryOperator<T>
public class StreamReduceExample {
    public static void main(String[] args) {
        List<Integer> listOfIntegers = Arrays.asList(1,2,3,4);
        Integer result  = listOfIntegers.stream()
                .reduce(1, (a,b) -> a*b);
        System.out.println("Multiplication result: " +result);
    }
} // Multiplication result: 24

How reduce() works iteratively in streams?

In the above coding snippet, 1 (identity) is given the default value. As we know second parameter is BinaryOperator<>, it is a Function(Functional Interface) which takes two inputs of same type and return value of same type. So first pass, we will have 1(default)*1(Stream), then in second pass;result of 1 pass * 2(Stream) and so on. Also, if we don’t specify default value, instead of returning concrete value, resultant would an Optional<>.

Stream API – limit() and Skip()

These two functions are useful in creating sub-streams or truncated streams.

  1. limit(n): limits the number of elements to be processed in a stream.
  2. skip(n): Applies offset while processing streams or just skip those many elements before processing.
public class StreamSkipNLimitExample {
    public static void main(String[] args) {
        List<Integer> listOfIntegers = Arrays.asList(1,2,3,4,5,6,7);

        Optional<Integer> result  = listOfIntegers.stream()
                .limit(4)
                .skip(2)
                .reduce((a,b) -> a*b);

        if (result.isPresent()) {
            System.out.println("Multiplication result: " + result.get());
        }
    }
} //Multiplication result: 12

In the above example, the sub stream will only have [3,4] as the limit includes first 4 elements [1,2,3,4] but we also applied skip(2). Therefore, only [3,4] left in the sub stream for further processing.

Stream API – anyMatch(), allMatch(), noneMatch()

All these functions takes in predicates and returns a boolean.

  1. anyMatch(): returns true if a condition is met even once.
  2. allMatch(): returns true w犀利士 hen all the element matches the predicate.
  3. noneMatch(): returns true when none of the element matches the predicate.
public class StreamMatchExample {

    public static boolean allMatch(){
        return EmployeDatabase.getEmployees().stream()
                .allMatch(em->em.getSalaryPerAnnum()> 9);
    }
    public static boolean anyMatch(){
        return EmployeDatabase.getEmployees().stream()
                .anyMatch(em->em.getSalaryPerAnnum()> 8);
    }
    public static boolean noneMatch(){
        return EmployeDatabase.getEmployees().stream()
                .noneMatch(em->em.getSalaryPerAnnum() < 4);
    }
    public static void main(String[] args) {
        System.out.println("Any match results :" +anyMatch());
        System.out.println("All match results :" +allMatch());
        System.out.println("None match results :" +noneMatch());
    }
}
//Any match results :true
//All match results :false
//None match results :true

Stream API – findFirst(), findAny()

Find operations are used to fetch elements based on predicate within a Stream. Also, both the functions return <Optional>.

  1. findFirst(): Returns the first element matching to predicate.
  2. findAny(): Returns the first encountered element matching to predicate.

How can we implement short-circuiting in Stream API?

short circuiting means, processing in a partial manner. Suppose we don’t want to process entire stream. Instead, process it partially or to stop processing after some conditions are met.

Short-circuiting in Stream API can be done via limit(), match and find operations wherein full stream is not processed usually.

How can we debug streams?

We can use peek() to debug stream. Peek can take a parameter as a Consumer Interface where we can print the current state of an Object in a stream.

In the next post we will learning about factory methods to create stream and terminal operations.

Hope you have enjoyed this post. Keep reading!!

Happy Learning.

Relevant Posts:

  1. Stream API Introduction
  2. Stream API Operations – Part 1
  3. Java Lambda Functional Interfaces
  4. Java Lambda Expressions- Basics