Java 8 stream filter
Filter as the name implies removing the unwanted things or data. In relation to java 8 streams, we might want to remove the items from the stream that do not meet certain criteria.
Examples, removing multiples of 5 from a list of integers, get employees from a certain department and so on.
In this article, we will be looking at how to filter stream in java based on single or multiple conditions with examples.
Java streams have a
filter()
method which is used to filtering out(or removing) elements from a stream based on a condition.filter()
method takes a Predicate as argument which is the condition for matching elements.Stream elements which do not meet this condition are removed from the resulting stream.
In other words, stream elements for which the predicate returns true
are added to the resultant stream, rest are filtered out.
Filter list of numbers
Below is an example to filter a list of integers and remove elements that are not a multiple of 5.
// create a list of integers List<Integer> numbers = List.of(12, 15, 34, 10, 300, 24, 45); /* filter elements which are * not divisible by 5 */ Stream<Integer> stream = numbers. stream(). filter( num -> num % 5 != 0 );
Notice the argument to filter()
method, it is a predicate which is represented as a Lambda expression(highlighted above).
Predicate
is a functional interface having a single method test()
which takes one argument and returns a boolean value.
So, it can be represented as a Lambda expression as
num -> num % 5 !=0
filter()
method is invoked on each stream element and tested against the given Predicate or condition. Elements for which the predicate condition returns boolean true
are added to the resulting stream.
Note that the return type of filter()
method is also a stream. Also remember that filter()
does not modify the original stream, a new stream with filtered elements is created.
Above example filtered the original stream and created a new stream. Now, you can perform following actions with this new stream.
- Iterate over the stream to print its elements, or
- Collect these elements into a new list.
Both examples are given ahead.
A. Iterate filtered stream
Iterate the stream using forEach()
method as shown below.
// create a list of string List<String> terms = List.of( "Lambda-java", "Dictionary-python", "Predicate-java", "Arrow-javascript", "Autowire-Spring"); /* filter elements which * are not divisible by 5 */ Stream<String> javaTerms = terms. stream(). filter( term -> term.contains("-java") ); System.out.println("Java terms are: "); /* iterate stream and * print its elements */ javaTerms.forEach( term -> System.out.println(term) );
This example checks if each stream element contains a string using contains()
method and produces following output
Java terms are:
Lambda-java
Predicate-java
Arrow-javascript
B. Collect filtered stream into a list
Below example filters a stream and collects it elements into a new list using collect()
method of stream.
// create a list of integers List<Integer> numbers = List.of(12, 15, 34, 10, 300, 24, 45); /* filter elements which are * not divisible by 5 */ Stream<Integer> stream = numbers. stream(). filter(num -> num % 5 != 0); System.out.println("Non-multiples of 5 are: "); // filtered elements to a list List<Integer> list = stream. collect(Collectors.toList()); System.out.println(list);
It produces following output
Non-multiples of 5 are:
[12, 34, 24]
Suppose we have a list of students of engineering batch.
Student
class is given below. public class Student { private int studentId; private String branch; public Student(int studentId, String branch) { this.studentId = studentId; this.branch = branch; } public String getBranch() { return branch; } @Override public String toString() { return "Student [studentId=" + studentId + ", branch=" + branch + "]"; } }
and we want students of only Computer Science branch.
We can filter a stream of object on the basis of its property or instance variable. Student
class has two properties.
Example to filter list of students based on their branch property is given below.
// create student objects Student s1 = new Student(232, "Electronics"); Student s2 = new Student(233, "Computer Science"); Student s3 = new Student(234, "Electrical"); Student s4 = new Student(235, "Computer Science"); Student s5 = new Student(236, "Mechanical"); List<Student> students = new ArrayList<>(); // add students to list students.add(s1); students.add(s2); students.add(s3); students.add(s4); students.add(s5); System.out.println("Students of given branch are:"); // filter students by property value Stream<Student> stream = students. stream(). filter( s -> s.getBranch().equals("Computer Science") ); // iterate list csStudents.forEach( st -> System.out.println(st) );
which produces below output
Students of given branch are:
Student {studentId=233, branch=Computer Science}
Student {studentId=235, branch=Computer Science}
Stream filter multiple conditions
Till now, we looked at filtering stream based on only one condition but we can also provide multiple filter conditions using logical AND(&&) or logical OR(||
) operators.
Suppose, from a list of numbers, we want only those numbers which are
A. multiples of 5, and
B. lesser than 100.
We can write a predicate for filter()
method which has both these conditions as shown below.
// create a list of integers List<Integer> numbers = List.of(12, 15, 34, 10, 300, 24, 45); // filter elements which are not divisible by 5 // and lesser than 100 Stream<Integer> stream = numbers. stream(). filter( num -> num % 5 == 0 && num < 100 ); System.out.println("Multiples of 5 less than 100 are: "); // filtered elements to a list List<Integer> list = stream.collect(Collectors.toList()); System.out.println(multiplesOf5List);
It outputs
Multiples of 5 less than 100 are:
[15, 10, 45]