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 8 stream filter() method
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.

  1. Iterate over the stream to print its elements, or
  2. 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]

Filter list of objects
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]

Hope the article was useful.

Leave a Reply