Java 8 filter + Stream Code Example

In the last couple of Java 8 tutorials, you have learned how to use map(), flatMap(), and other stream methods to get an understanding of how Java 8 Stream and Lambda expressions make it easy to perform the bulk data operation on Collection classes like List or Set. In this Java 8 tutorial, I am going to share how to use the filter() method in Java 8, another key method of Stream class.  This is the one method you will always be used because it forms the key part of Stream pipeline. If you have seen some Java 8 code, you would have already seen this method a couple of time. The filter() method as its name suggests is used to perform filtering based upon some boolean conditions.  The condition is applied to each element of Stream and those who pass the condition moves to the next stage and those who don't get filtered out.

For example,  if you have a stream of integral numbers which contains both even and odd numbers then by using filter method, you can create another stream of even numbers or odd numbers by filtering out others.

Though, filter() method is little bit of counter-intuitive, I mean, in order to create a stream of even number you call filter( i -> i % 2 == 0) which means you do filter(isEven()) but, you are actually filtering out odd numbers to create a new stream of even numbers, but that's how it works.

I think select() would have been a positive and proper name for this operation, but, we don't have any control over that can't change that now.

The key benefit of using filter() method is lazy evaluation i.e. no data comparison is performed unless you call a terminal operation on stream like findFirst() or forEach().

The filter() method just set up some pointers when you first call them on stream and only performs real filtering when you call the terminal method. You can join a good Java course like The Complete Java MasterClass to learn more about Stream and lazy evaluation in Java 8. It is also one of the most up-to-date course, recently updated for Java 11.




How filter method works in Java 8

In order to learn how to use the filter() method in Java 8, it's important that you also know how it works, at least at a high level. Let's see an example of filter() method to understand the lazy evaluation it does.

Suppose we have a list of integer numbers and we want to find the first number which is divisible by both 2 and 3, let' see how to solve this problem in Java 8.

List<Integer> listOfNumbers = Arrays.asList(1, 2, 3, 4, 5, 6, 12, 18);
Integer lcm = listOfNumbers.stream()
                           .filter(i -> i % 2 == 0)
                           .filter(i -> i % 3 == 0)
                           .findFirst().get();        

This code is returning the first the first number which is divisible by both 2 and 3. Now, let's see how this code will execute. When you call the filter() method nothing happens until you call the findFirst().

At this time, Java knows that it just need to find the first element which satisfies the criterion imposed by the two chained filter() methods.

The findFirst() ask the filter() method prior to it in the chain of any number, the filter doesn't have any record so it asks the first filter() method, which in turn then scan the list and return a number which is divisible by 2.

At this time, second filter method checks if this number is divisible by 3, if yes then it returns that number to findFirst() otherwise it asks another number from first filter() method.

This process continues until a number is found which satisfy both filter() methods. Once that number is found it presented to findFirst() method. The job of findFirst() is to return that number.

This is an example of lazy evaluation because nothing happens until the call to findFirst() is a method, this also presents an opportunity to stop as soon as you find the first number which satisfies your criterion.

There is no need to process the entire list again and again, as it happens in the case of iterative eager evaluation.  You can read more about Stream Processing and Lazy Evaluation on Pluralsight's From Collections to Streams in Java 8 Using Lambda Expressions course by Jose Paumard, a Java Champion and expert Java Programmer.


Java 8 filter + Stream Example




Java 8 filter Example

Here are a couple of more examples of Stream.filter() method in Java 8. I have created a list of String containing Android versions like  LolliPop, KitKat etc.

The first example just uses one filter() method to print Strings whose length is greater than 10. The second example prints String which contains the letter "e" like Gingerbread.

The Third examples combine these two filter methods to create a chain of filter methods to print String whose length is greater than 5 and starts with a letter "G".

By the way, for testing purpose, you can also create a stream of integers number by using Stream.of() static factory methods as shown in the following example:

How to use filter method in Java 8 with example

You can see that the input stream contains numbers from 1 to 5 but the output stream just contains odd numbers. This means even numbers were filtered out because they didn't satisfy the boolean condition specified by Predicate.

I mean for even number x%2 == 0 and we are checking for x%2 !=0 so they didn't pass the condition and hence not progressed to the output stream. If you need more examples, I suggest you check out the Java Streams API Developer Guide by Nelson Djalo, one of the hands-on course on learning Stream examples live.



How to use filter() method in Java 8

Here is a sample Java program to demonstrate how to use the filter() method of Stream class to filter elements from a List or Stream, based upon some conditions, specified by Predicate functional interface of Java 8.

package test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Java 8 filter example. You can use filter() method to perform lazy filtering
 * in Java.
 */
public class Java8FilterExample {

    public static void main(String[] args) {

        List<String> versions = new ArrayList<>();
        versions.add("Lollipop");
        versions.add("KitKat");
        versions.add("Jelly Bean");
        versions.add("Ice Cream Sandwidth");
        versions.add("Honeycomb");
        versions.add("Gingerbread");

        // Using one filter() 
        // print all versions whose length is greater than 10 character
        System.out.println("All versions whose length greater than 10");
        versions.stream()
                .filter(s -> s.length() > 10)
                .forEach(System.out::println);

        System.out.println("first element which has letter 'e' ");
        String first = versions.stream()
                .filter(s -> s.contains("e"))
                .findFirst().get();
        System.out.println(first);
        

        // Using multiple filter
        System.out.println("Element whose length is > 5 and startswith G");
        versions.stream()
                .filter(s -> s.length() > 8)
                .filter(s -> s.startsWith("G"))
                .forEach(System.out::println);
        

        // another example of filter() method in Java 8
        List<Integer> listOfNumbers = Arrays.asList(1, 2, 3, 4, 5, 6, 12, 18);
        Integer lcm = listOfNumbers.stream()
                .filter(i -> i % 2 == 0)
                .filter(i -> i % 3 == 0)
                .findFirst().get();
        System.out.println("first number divisible by 2 and 3 in the list is : "
                                  + lcm);

    }

}

Output
All versions whose length greater than 10
Ice Cream Sandwidth
Gingerbread
first element which has letter 'e' 
Jelly Bean
Element whose length is > 5 and starts with G
Gingerbread
a first number divisible by 2 and 3 in the list is : 6


That's all in this Java 8 filter() example. It's one of the most useful methods of Stream class and you will find yourself using this method time and again. The best part of this method is that it improves performance by doing lazy evaluation.

The filter() method just setup couple of pointers and no data comparison is performed until a terminal method e.g. forEach() or findFirst() is called.

You can see the Java documentation of filter() method to learn more about it, you can also read check out the following resources to learn more about Stream and other major enhancements made in Java 8.

Further Learning
The Complete Java MasterClass
Java SE 8 for Really Impatient
From Collections to Streams in Java 8 Using Lambda Expressions


Related Java 8 tutorials you may like
  • 5 Free Courses to learn Java 8 and 9 (courses)
  • 20 Example of Date and Time API in Java 8 (click here)
  • 10 Examples of Lambda Expression in Java 8 (click here)
  • 5 Books to Learn Java 8 Better? (read here)
  • 10 Examples of converting a List to Map in Java 8 (see here)
  • Difference between Stream.map() and Stream.flatMap() in Java 8? (answer)
  • Java 8 Comparator Example (check here)
  • Collection of best Java 8 tutorials (click here)
  • 10 Examples of Stream in Java 8 (example)
  • Difference between abstract class and interface in Java 8? (answer)
  • 10 Free Courses for Experienced Java Programmers (courses)
  • How to sort the may by values in Java 8? (example)
  • How to format/parse the date with LocalDateTime in Java 8? (tutorial)
  • Top 5 Course to master Java 8 Programming (courses)
  • Java 8 Interview Questions and Answers (questions)
Thanks for reading this article so far. If you like this Java 8 filter method tutorial then please share with your friends and colleagues. If you have any questions or feedback then please drop a note.


P.S.: If you just want to learn more about new features in Java 8 then please see the course What's New in Java 8. It explains all the important features of Java 8 e.g. lambda expressions, streams, functional interfaces, Optional, new Date Time API and other miscellaneous changes.

1 comment:

  1. public class FilterMapper {
    private static final Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) {
    List names = Arrays.asList(
    "aaryanna",
    "aayanna",
    "airianna",
    "alassandra",
    "allanna",
    "allannah",
    "allessandra",
    "allianna",
    "allyanna",
    "anastaisa",
    "anastashia",
    "anastasia",
    "annabella",
    "annabelle",
    "annebelle"
    );

    names.stream()
    .filter(Filter.nameStartingWithPrefix(scanner.nextLine()))
    .map(Mapper.getDistinctCharactersCount())
    .forEachOrdered(System.out::println);
    }
    }

    class Filter{

    }




    // can you please help me how can i call names List in Filter class to found prefix in method nameStartingWithPrefix().

    thank you

    ReplyDelete