Skip to content
Related Articles

Related Articles

Improve Article

How Java filter() Method Works in Background?

  • Last Updated : 21 Apr, 2021

 filter() method is used in functional programming as an intermediate method. A predicate is a non-interfering, stateless predicate to apply to each element to determine if it should be included.

Syntax: filter() method 

filter(Predicate predicate)

Parameter: A predicate

Return Type: A stream consisting of the elements of the passed stream that match the given predicate.

Have you ever wondered what is happening when we write the below sample that is a lambda expression with an element mapping to an ‘element%2==0? So what actually is happening behind the screens, how is it actually working? All the magic of this is based on something which is called a Functional Interface as the functional interface has exactly one abstract method. Since default methods have an implementation, they are not abstract. For example Predicate Interface, Consumer Interface are functional interfaces.



List.of(10,5,23,54).stream().filter(element -> element%2==0);

Implementation: Consider the program below which uses the filter() method to eliminate the odd numbers and returns the stream of numbers that are divisible by 2 that is even numbers.

Example 1:

Java




// Java Program to deminstarte Use of filter() Method
  
// Importing all. input output classes
import java.io.*;
// Importing List class from java.util package
import java.util.List;
  
// Main class
class GFG {
  
    // Main driver method
    public static void main(String[] args)
    {
  
        // 1. Creating List of integers later on
        // 2. converting List to a Stream in which
        // 3. logic is to eliminate the odd numbers and
        // finally
        // 4. Printing each element of stream returned by
        // filter() method
        List.of(12, 34, 67, 19, 32, 4)
            .stream()
            .filter(element -> element % 2 == 0)
            .forEach(
                element -> System.out.println(element));
    }
}
Output
12
34
32
4

Internal workflow

  • When the stream of [12, 34, 67, 19, 32, 4] is passed to the filter method, it tests each element using the provided predicate (element → element%2==0) and returns the stream of even numbers [12, 34, 32, 4].
  • Now, what is happening behind the screens? How does the code fragment ‘element  → element%2 == 0 ‘ get sent out to the filter method.
  • If we look at the signature of the filter() method is as follows where one can see that it is taking a Predicate in the argument.
public abstract Stream<T> filter(Predicate<? super T> predicate)
  • So when we go to the documentation of Predicate, it has the following signature is as follows with @FunctionalInterface annotation written above it
public interface Predicate<T>
  • The functional method which is present in this Predicate interface is as follows:
boolean Test(T t) ;
  • It returns a composed predicate that represents a logical AND of this predicate and another.  When evaluating the composed predicate, if this predicate is false, then the other predicate is not evaluated.
  • In the predicate interface, Test() is the only method that does not have any default implementation written. So now, how does ‘element -> element%2 == 0‘ gets mapped to the implementation of the Predicate interface.
  • We are having a method test() which is accepting an interface Predicate as an argument, then we can only pass the objects of the implementations of that interface as parameters to that method.

Example 2:

Java




// Java Program to Implementation of the Predicate interface
  
// Importing input output classes
import java.io.*;
// Importing classes from java.util package
import java.util.List;
import java.util.function.Predicate;
  
// Class 1
// helper class
// Implementation of Predicate interface
class EvenNumberPredicate implements Predicate<Integer> {
  
    // Implementing all unimplemented method of the
    // Predicate interface.
    // @Override
    public boolean test(Integer number)
    {
  
        // Returns true for Even and false for Odd
        return number % 2 == 0;
    }
}
  
// Class 2
// Main class
class GFG {
  
    // Main driver method
    public static void main(String[] args)
    {
  
        // 1. Creating List of integers then
        // 2. Converting list to stream further
        // 3. Passing the object of Predicate to the filter
        // mehtod
        List.of(12, 34, 67, 19, 32, 4)
            .stream()
            .filter(new EvenNumberPredicate())
            .forEach(
                element -> System.out.println(element));
    }
}
Output
12
34
32
4

Note: Both of the programs produces the same output.

When we pass the object of EvenNumberPredicate() to the filter method as an argument, what it does is for every element of the stream passed to it, it will check the condition provided in the overridden test() method of EvenNumberPredicate() and it includes the element to the returning stream if test() returns true, else it refuses to include the element to the returning stream if test() method returns false. For example: for element 12, test() method returns true, so it is included in the returning stream, while for the element 67 test() returns false, so 67 is not included in the returning stream. Example 2 shows exactly what is happening when we pass some logic to the filter() method. This means, when we pass some logic to the filter() method, the java compiler in the background creates an implementation of the functional interface.

Note: The most important feature of a functional interface just like Predicate is that it would have only one method which will not have a definition, and basically what we are doing when we are creating a Lambda Expression is that we are providing implementation (or logical code) for that specific method.

In this case (i.e. filter()) we are saying to the compiler that takes the only method which is not implemented test() in the case of Predicate and provides the logic written in the filter method as the implementation for it. 

Attention reader! Don’t stop learning now. Get hold of all the important Java Foundation and Collections concepts with the Fundamentals of Java and Java Collections Course at a student-friendly price and become industry ready. To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.




My Personal Notes arrow_drop_up
Recommended Articles
Page :