Java Stream filter
last modified May 25, 2025
In this article, we explore how to efficiently filter Java streams using filtering operations. Filtering is a fundamental technique in functional programming that helps refine datasets, extract relevant information, and streamline data processing within Java streams.
A Java Stream represents a sequence of elements originating from a data source, supporting various aggregate operations such as filtering, mapping, reducing, and sorting. Unlike collections, streams do not store elements permanently; instead, they process elements on demand, making them highly efficient for large datasets. Java streams can operate on collections, arrays, I/O resources, and other sources, providing a functional approach to data manipulation.
Stream aggregate operations resemble SQL queries, allowing developers to perform sophisticated data transformations with minimal code. Through functional programming principles, streams enable operations such as:
- Filtering: Selecting elements based on conditions.
- Mapping: Transforming elements from one form to another.
- Reducing: Aggregating elements to compute a summary result.
- Matching: Checking if elements meet specific criteria.
- Sorting: Ordering elements efficiently.
One of the key benefits of Java streams is their ability to chain multiple operations, leading to concise, readable, and highly efficient code. Unlike traditional collections, which rely on external iteration, Java streams utilize internal iteration, delegating execution control to the runtime for optimized processing.
The filter Method
The Java Stream filter
method is an intermediate operation,
designed to select elements that meet a specified condition. It takes a
predicate function, which evaluates each element and returns a boolean value
indicating whether the element should be included in the final stream.
This method is particularly useful when working with large datasets, allowing developers to refine and extract relevant data without modifying the original collection.
The filter
method can be combined with other stream operations for
complex data processing, making Java streams a powerful tool for modern
application development.
Filter by string length
The following example filters a list of strings.
void main() { List<String> words = List.of("pen", "custom", "orphanage", "forest", "bubble", "butterfly"); List<String> result = words.stream().filter(word -> word.length() > 5).toList(); result.forEach(System.out::println); }
We have a list of words. We filter the list to include only strings whose length is bigger than five.
List<String> result = words.stream().filter(word -> word.length() > 5).toList();
With the stream
method, we create a Java Stream from a list of
strings. On this stream, we apply the filter
method. The
filter
method accepts an anonymous functions that returns a boolean
true for all elements of the stream whose length is bigger that five.
result.forEach(System.out::println);
We go through the result with the forEach
method and print all its
elements to the console.
$ java Main.java custom orphanage forest bubble butterfly
Filter null values
The next example filters out null
values.
void main() { List<String> words = new ArrayList<>(); words.add("cup"); words.add(null); words.add("forest"); words.add("sky"); words.add("book"); words.add(null); words.add("theatre"); List<String> result = words.stream().filter(Objects::nonNull).toList(); System.out.println(result); }
We have a list of words. With the Stream filtering operation, we create a new
list with null
values discarded.
List<String> result = words.stream().filter(Objects::nonNull).toList();
In the body of the lambda expression, we check that the value is not
null
. The toList
method is a terminal operation that
creates a list from the filtered stream.
Multiple filter operations
It is possible to apply multiple filter operations on a stream.
void main() { int[] inums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; IntConsumer icons = i -> System.out.print(i + " "); Arrays.stream(inums).filter(e -> e < 6 || e > 10) .filter(e -> e % 2 == 0).forEach(icons); }
In the example, we apply multiple filter operations on a stream of integers.
int[] inums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
We have an array of integer values.
IntConsumer icons = i -> System.out.print(i + " ");
IntConsumer
is a functional interface that accepts an integer
value and performs an action on it. In this case, it prints the integer value
to the console.
Arrays.stream(inums).filter(e -> e < 6 || e > 10) .filter(e -> e % 2 == 0).forEach(icons);
A stream is created from the array with the Arrays.stream
method.
Multiple filtering operations are performed.
Filter objects
The next example shows how to filter objects.
void main() { List<User> persons = List.of( new User("Jack", "jack234@gmail.com"), new User("Peter", "pete2@post.com"), new User("Lucy", "lucy17@gmail.com"), new User("Robert", "bob56@post.com"), new User("Martin", "mato4@imail.com") ); List<User> result = persons.stream() .filter(person -> person.email().matches(".*post\\.com")) .toList(); result.forEach(p -> System.out.println(p.name())); } record User(String name, String email) { }
The example creates a stream of User
objects. It filters those
which match a specific regular expression.
List<User> result = persons.stream() .filter(person -> person.email().matches(".*post\\.com")) .toList();
In the filter predicate, we choose emails that match the
.*post\\.com
pattern.
Filtering users by age
The next example filters users by their age. We use the Period
class to calculate the age of a user based on their date of birth.
void main() { List<User> users = List.of( new User("John", "Doe", "1990-01-01"), new User("Jane", "Doe", "1985-05-15"), new User("Alice", "Smith", "2000-12-31"), new User("Paul", "Anka", "1965-11-04"), new User("Bob", "Brown", "1995-07-20"), new User("Charlie", "Johnson", "1980-03-10"), new User("Diana", "Prince", "1992-11-11") ); users.stream() .filter(user -> user.age() > 40) .forEach(user -> System.out.printf( "%s %s is %d years old%n", user.firstName(), user.lastName(), user.age())); } record User(String firstName, String lastName, String dateOfBirth) { int age() { return Period.between( LocalDate.parse(dateOfBirth), LocalDate.now()).getYears(); } }
The filter
method is used to select users older than 40 years.
$ java Main.java Paul Anka is 59 years old Charlie Johnson is 45 years old
Filter map by keys
In the following example, we filter a map by its keys. The key is retrived using
the getKey
method of the Map.Entry
interface.
void main() { Map<String, String> hmap = new HashMap<>(); hmap.put("de", "Germany"); hmap.put("hu", "Hungary"); hmap.put("sk", "Slovakia"); hmap.put("si", "Slovenia"); hmap.put("so", "Somalia"); hmap.put("us", "United States"); hmap.put("ru", "Russia"); hmap.entrySet().stream().filter(map -> map.getKey().startsWith("s")) .forEach(System.out::println); }
The example filters domain names starting with s letter. We use the
getKey
method to retrieve the key of the map entry and check if it
starts with the letter s
using the startsWith
method.
Filter map by values
In the following example, we filter a map by its values. The value is
retrieved using the getValue
method of the Map.Entry
interface.
void main() { Map<String, String> countries = new HashMap<>(); countries.put("de", "Germany"); countries.put("hu", "Hungary"); countries.put("sk", "Slovakia"); countries.put("si", "Slovenia"); countries.put("so", "Somalia"); countries.put("us", "United States"); countries.put("ru", "Russia"); countries.entrySet().stream().filter(country -> country.getValue().equals("Slovakia") || country.getValue().equals("Slovenia")) .forEach(System.out::println); }
In the example, we filter out two countries from the map. We use the
getValue
method to retrieve the value of the map entry and check if
it equals either "Slovakia" or "Slovenia" using the equals
method.
Source
In this article we have have worked with Java Stream filtering operations.
Author
List all Java tutorials.