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.