Signup/Sign In
PUBLISHED ON: AUGUST 6, 2021

Java Stream Filter

A Stream in Java is a sequence of elements or objects. Streams are introduced in Java 8. They allow us to perform various operations on a data source in an efficient manner.

In this tutorial, we will learn how to filter streams in Java.

Stream.filter() Method

The filter() method of Streams allows us to filter a given stream based on a condition or a predicate.

Note that this method will not alter the given stream. It will return a new stream that contains the elements satisfying the condition. The signature of the method is shown below.

Stream<T> filter(Predicate<? super T> condition)  

Let's take a look at a few examples to understand its working.

Example 1: Filter Stream in Java

Let's filter out all the elements greater than 7 from a Stream. We will create a Stream from a List and then apply the filter() method on this Stream.

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class Demo
{
	public static void main(String[] args)
	{
		List<Integer> list = Arrays.asList(7, 9, 1, 2, 5, 11, 21);
		System.out.println("The List is: " + list);
		
		Predicate<Integer> numGreaterThanSeven = p -> (p > 7);//Writing the condition or Predicate
		
		Stream<Integer> s = list.stream();//Stream of the list
		Stream<Integer> filteredStream = s.filter(numGreaterThanSeven);
		
		System.out.println("Filtered Elements are: ");
		filteredStream.forEach(System.out :: println);
	}
}


The List is: [7, 9, 1, 2, 5, 11, 21]
Filtered Elements are:
9
11
21

Example 2: Filter Stream of User data

Let's work on a user-defined class. We will create the Student class defined below.

class Student
{
	private String name;
	private int regNo;
	private Double gpa;
	
	Student(String s, int i, Double gpa)
	{
		this.name = s;
		this.regNo = i;
		this.gpa = gpa;
	}    
    //Getters and Setters
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getRegNo() {
		return regNo;
	}
	public void setRegNo(int regNo) {
		this.regNo = regNo;
	}
	public Double getGpa() {
		return gpa;
	}
	public void setGpa(Double gpa) {
		this.gpa = gpa;
	}	
}

Let's filter out all Students whose GPA is greater than 8. We will create a Predicate for this condition and use it with the filter() method.

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Stream;

public class Demo
{
	public static void main(String[] args)
	{
		Student s1 = new Student("Jack", 102, 8.55);
		Student s2 = new Student("Joe", 101, 8.75);
		Student s3 = new Student("Clay", 107, 9.1);
		Student s4 = new Student("Simon", 105, 7.99);
		Student s5 = new Student("Reacher", 103, 7.00);
		
		List<Student> list = Arrays.asList(s1, s2, s3, s4, s5);
				
		Predicate<Student> gpaGreaterThanEight = c -> c.getGpa() > 8.0;//Lambda expression for Predicate
		
		Stream filteredStream = list.stream().filter(gpaGreaterThanEight);
	}
}

We can also define a method in the Student class that returns a boolean value. Then, we can use this method directly with the filter() method. We will collect the filtered stream into a List by using the collect() method.

public boolean gpaGreaterThanEight()
{
	return this.getGpa() > 8.0;
}
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;


public class Demo
{
	public static void main(String[] args)
	{
		Student s1 = new Student("Jack", 102, 8.55);
		Student s2 = new Student("Joe", 101, 8.75);
		Student s3 = new Student("Clay", 107, 9.1);
		Student s4 = new Student("Simon", 105, 7.99);
		Student s5 = new Student("Reacher", 103, 7.00);

		List<Student> list = Arrays.asList(s1, s2, s3, s4, s5);
		System.out.println("The Student List is: ");
		for(Student s : list)
			System.out.println(s.getName() + " " + s.getRegNo() + " " + s.getGpa());
	
		Stream filteredStream = list.stream().filter(Student :: gpaGreaterThanEight);//Class Method for Predicate 
		List<Student> filteredList = (List<Student>) filteredStream.collect(Collectors.toList());
		
		System.out.println("\nThe Filtered List is: ");
		for(Student s : filteredList)
			System.out.println(s.getName() + " " + s.getRegNo() + " " + s.getGpa());
	}
}


The Student List is:
Jack 102 8.55
Joe 101 8.75
Clay 107 9.1
Simon 105 7.99
Reacher 103 7.0

The Filtered List is:
Jack 102 8.55
Joe 101 8.75
Clay 107 9.1

Example 3: Filter Stream by using Lambda Expression

We can also use multiple conditions for filtering. These conditions can be created using Lambda expressions in the Predicate. Or we can create a method in the user-defined class(if we are using a user-defined class). Let's continue with the previous example and filter out all Students whose GPA is greater than eight and name contains exactly three characters.

Let's first use a Lambda expression to accomplish our task.

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Demo
{
	public static void main(String[] args)
	{
		Student s1 = new Student("Jack", 102, 8.55);
		Student s2 = new Student("Joe", 101, 8.75);
		Student s3 = new Student("Clay", 107, 9.1);
		Student s4 = new Student("Simon", 105, 7.99);
		Student s5 = new Student("Reacher", 103, 7.00);

		List<Student> list = Arrays.asList(s1, s2, s3, s4, s5);
		System.out.println("The Student List is: ");
		for(Student s : list)
			System.out.println(s.getName() + " " + s.getRegNo() + " " + s.getGpa());
	
		Predicate<Student> p = c -> (c.getGpa() > 8.0) && (c.getName().length() == 3);
		
		Stream filteredStream = list.stream().filter(p);
		List<Student> filteredList = (List<Student>) filteredStream.collect(Collectors.toList());
		
		System.out.println("\nThe Filtered List is: ");
		for(Student s : filteredList)
			System.out.println(s.getName() + " " + s.getRegNo() + " " + s.getGpa());
	}
}


The Student List is:
Jack 102 8.55
Joe 101 8.75
Clay 107 9.1
Simon 105 7.99
Reacher 103 7.0

The Filtered List is:
Joe 101 8.75

Let's define a method in the Student class that checks the two conditions and returns a boolean value accordingly.

public boolean predicateCondition()
{
	if(this.getGpa() > 8.0 && this.getName().length() == 3)
		return true;
	else
		return false;
}
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Demo
{
	public static void main(String[] args)
	{
		Student s1 = new Student("Jack", 102, 8.55);
		Student s2 = new Student("Joe", 101, 8.75);
		Student s3 = new Student("Clay", 107, 9.1);
		Student s4 = new Student("Simon", 105, 7.99);
		Student s5 = new Student("Reacher", 103, 7.00);

		List<Student> list = Arrays.asList(s1, s2, s3, s4, s5);
		System.out.println("The Student List is: ");
		for(Student s : list)
			System.out.println(s.getName() + " " + s.getRegNo() + " " + s.getGpa());
		
		Stream filteredStream = list.stream().filter(Student :: predicateCondition);
		List<Student> filteredList = (List<Student>) filteredStream.collect(Collectors.toList());
		
		System.out.println("\nThe Filtered List is: ");
		for(Student s : filteredList)
			System.out.println(s.getName() + " " + s.getRegNo() + " " + s.getGpa());
	}
}


The Student List is:
Jack 102 8.55
Joe 101 8.75
Clay 107 9.1
Simon 105 7.99
Reacher 103 7.0

The Filtered List is:
Joe 101 8.75

Exception Handling in Lambda Expression

A checked or unchecked exception may occur in our Lambda expression that we use for Predicates. It is a good idea to use try-catch blocks in lambda expressions to handle exceptions.

Predicate<Student> p = c ->
                   {
			           try{
				           return c.predicateCondition(); 
			           }
			           catch(Exception e) {
				           System.out.print(e);
			           }
			           return false;
		           };

We can also use third-party libraries like the ThrowingFunction library to handle checked exceptions. We will use the ThrowingPredicate class of this library. It will return a wrapped exception.

try
{
		List<Student> customersWithValidProfilePhoto = list
					  .stream()
					  .filter(ThrowingPredicate.unchecked(Student :: predicateCondition))
					  .collect(Collectors.toList());
}
catch(Exception e)
{
		System.out.print(e);
}

If an exception occurs in the above code, then we will get the following output.


pl.touk.throwing.exception.WrappedException

Summary

A Stream is just a sequence of elements. The filter() method allows us to filter out elements from a Stream based on a condition. The condition is defined using a Predicate. We can either use Lambda Expressions or class methods(for user-defined classes) to create a Predicate. The Predicate plays a crucial role in determining how the elements will be filtered.



About the author:
I am a 3rd-year Computer Science Engineering student at Vellore Institute of Technology. I like to play around with new technologies and love to code.