Filtering of a list is a commonly performed method to select elements from the List that fulfill specified criteria. This filtration is performed to gain the required result from the data according to the provided query. For instance, the filter of an e-commerce website fetches or filters the result or products based on a user-provided query.

This guide explains the procedure to filter a list in Java.

How to Filter a List in Java?

There are various methods provided by Java to filter a List according to its requirements. The user can filter out elements that have the same starting characters, ending characters, matching words, and many more. This filtration of the List can be done via several approaches which are satiated below:

  • Method 1: Stream API in Java 8 “filter()” Method
  • Method 2: Filter a List Using Predicate Interface
  • Method 3: Filter a List Using “Filter Interface” in Java
  • Method 4: Filter a List Using the Guava “FluentIterable” Class in Java

Method 1: Filtering a List Using Java 8 Stream API

Java 8 offers a Stream API which provides methods like “filter()”, “map()”, and “collect()” to filter a list. These methods work in combination to traverse through provided data, remove unrequired elements, and leave the filtered lists as a result:

  • The “filter()” method filters a list according to criteria set by the lambda function.
  • The “map()” places or transforms the elements into another collection.
  • The “collect()” method repacks or folds the filtered stream elements into another collection. 

Take a look at the provided examples to filter a list using the Java 8 stream API “filter()” method.

Example 1: Filter a List Using “filter()” Method

In this case, the “filter()” method and lambda functions are used in combination to filter the list of elements that start with a specified character:

import java.util.stream.Stream;
public class Filtering {
public static void main(String args[]){
  Stream<String> listStream = Stream.of("Javac", "Ada", "ALGOL", "Java");
  Stream<String> filtering = listStream.filter(str -> str.startsWith("A"));
  System.out.print("The Filtered List is: \n");
  filtering.forEach(str->System.out.print( str + "\n"));
}
}

In the above code snippet:

  • First, import the “stream.Stream” utility and create a class “Filtering”. Inside it, pass the list elements over the Stream named “listStream”. 
  • Now, apply a “filter()” method on the “listStream” and pass the “lambda” function as an argument.  This lambda function uses the “startsWith()” method to select elements that start with a specified character.
  • Store the selected elements in another Stream named “filtering”. Then, print the elements of this Stream on the console using the “forEach()” method.

Pro Tip:

  • To select an element of a list that ends with specific characters, use the “endsWith()” method. 
  • To select all elements that contain a specific character, use the “contains()” method.

The generated output confirms the filtering of List elements:

Example 2: Filter a List Using “filter()” and “collect()” Method

To insert the filtered elements into another collection use the combination of “filter()” and “collect()” methods. The collection in which the elements need to be inserted is “List” and this process is processed using the “toList()” method of the “Collectors” class:

import java.util.*;
import java.util.stream.*;
public class Filtering{
public static void main(String args[]){
  List<String> origList = Arrays.asList("Javac", "Ada", "ALGOL", "Java");
  System.out.print("The Orignal List is: " + origList);
  List<String> filtered = origList.stream()
              .filter(n -> n.endsWith("a"))
              .collect(Collectors.toList());
  System.out.print("\n\nThe Filtered List is: ");
  System.out.println(filtered);
}
}

In the above code snippet:

  • First, import the “util” and “stream” packages and create a class named “Filtering”.
  • Next, use the “Arrays.asList()” method to insert elements in the String type List named “origList”.
  • Then, pass this List over the Stream by attaching the “stream()” method. Apply the “filter” method which contains a lambda function to set the criteria of a Filter. 
  • Then, apply the “collect()” method which contains “Collectors.toList()” as an argument to convert the result into a List. Store the generated final output in a List named “filtered”.
  • This “filtered” list is then displayed on the console for verification purposes.

The output shows the generated filtered list:

Example 3: Filter a List Using “filter()” and “map()” Method

In Java 8 Stream API, the “map()” method transforms the generated result. In our case, it applies operations or appends a String with the filtered List:

import java.util.*;
import java.util.stream.*;
//Importing Libraries
public class Filtering{
public static void main(String args[]){
//Defining the Targeted List
  List<String> origList = Arrays.asList("Javac", "Ada", "ALGOL", "Java");
  System.out.print("The Orignal List is: " + origList);
//Performing Filter Operation
  List<String> filtered = origList.stream()
  .filter(n -> n.contains("a"))
  .map(n -> "Hello " + n)
  .collect(Collectors.toList());

  System.out.print("\n\nThe Filtered List is: ");
  System.out.println(filtered);
}
}

The description of the above code is as follows:

  • First, import the “java.util” and “java.util.stream” utilities using the “import” keyword.
  • Next, define a class “Filtering” and inside its “main()” method define a targeted List that needs to be filtered.
  • Then, apply the “stream()” and “filter()” methods just like done in the above example. Also, attach the “map()” method to append a dummy text with each filtered element.
  • After that, convert filtered elements into a list using the “Collectors.toList()” methods.
  • Store the converted elements into a “filtered” List which is then displayed on the console.

The generated output shows the filtering of a provided List:

Example 4: Filter a List by Applying Multiple “filter()” and “map()” Methods

The user can apply more than one “filter()” or “map()” method on a single Stream to filter a List according to their need. Multiple “filter()” and “map()” methods allow the user to apply more filter rules over the list and more transformation of the generated result:

import java.util.*;
import java.util.stream.*;
public class Filtering{
public static void main(String args[]){
  List<String> origList = Arrays.asList("Javac", "Ada", "ALGOL", "Java");
  System.out.print("The Orignal List is: " + origList);
  List<String> filtered = origList.stream()

  .filter(n -> n.contains("a"))
  .filter(n -> n.startsWith("J"))
  .map(n -> "Hello " + n)
  .map(n -> n + " Bro")

  .collect(Collectors.toList());
  System.out.print("\n\nThe Filtered List is: ");
  System.out.println(filtered);
}
}

The above code is the same as described in the previous example. The extra “filter()” method is applied to filter out elements that start with a specified character. An extra “map()” method is also applied to append dummy values with the filtered List elements.

The output shows the generation of a filtered List element:

Method 2: Filter a List Using Predicate Interface

A “predicate” is a functional interface provided by the “util.function.Predicate” package. It appears as a Boolean-type function that accepts a single argument and generates the result accordingly in “true” or “false”. In the case of filtering a List, the “predicate” passes the behavior of a function(Lambda) to the methods that apply the filtering rules over the List:

import java.util.*;
import java.util.function.Predicate;

class CODCharacter {
private String Name;
private double Age;
private double Salary;

public CODCharacter(String name, double age, double salary) {
  this.Name = name;
  this.Age = age;
  this.Salary = salary;
}
public String getName() {
  return Name;
}
public double getAge() {
  return Age;
}
public double getSalary() {
  return Salary;
}
}

public class Filtering{
public static void main(String... args) {
  List<CODCharacter> characters = new ArrayList<>();
  characters.add(new CODCharacter("Francis - Dark Opulence", 33, 60000.0));
  characters.add(new CODCharacter("Yegor - NightLife", 28, 40000.0));
  characters.add(new CODCharacter("Demir - Lurking Dread", 37, 110000.0));
  characters.add(new CODCharacter("Foxtrot - Unseen Angel", 32, 80000.0));
  characters.add(new CODCharacter("Roland - Vinterblood", 32, 95000.0));

The above code works like this:

  • First, import the “java.util.function.Predicate” and “java.util.*” packages via the “import” keyword.
  • Next, create a class “CODCharacter” and declare three “private” scoped variables named “Name”, “Age”, and “Salary”. Assign values to these variables by invoking the class constructor.
  • Also, create three getter methods named “getName()”, “getAge()”, and “getSalary()”. These methods return the initialized “Name”, “Age”, and “Salary” variables respectively.
  • Then, define a “main()” method and inside it create a List named “characters” with the reference of “CODCharacter”.
  • Invoke the class constructor and pass the values of each List element as its arguments. This constructor is then passed to the “add()” method. 
  • This “add()” method inserts each class instance as the value/element in the “characters” List.

Let’s define a custom predicate and a function in which this predicate is going to be applied on the original provided List:

// Predicate to filter characters with a salary above 70k
  Predicate<CODCharacter> highSalaryFilter = character -> character.getSalary() > 70000.0;
  List<CODCharacter> highSalaryCharacters = filterCharacters(characters, highSalaryFilter);

  System.out.println("Upcoming Characters with High Demand in Call of Duty:");
  for (CODCharacter elements: highSalaryCharacters) {
  System.out.println("\nName: " + elements.getName() + ", Age: " + elements.getAge() + ", Salary: $" + elements.getSalary());
  }
  }
private static List<CODCharacter> filterCharacters(List<CODCharacter> characters,
Predicate<CODCharacter> predicate) {
  List<CODCharacter> filteredList = new ArrayList<>();
  for (CODCharacter character: characters) {
    if (predicate.test(character)) {
    filteredList.add(character);
    }
  }
  return filteredList;
}
}

The working of above code is as follows:

  • Now, define an instance “highSalaryFilter” of the “Predicate” with the reference of “CODCharacter”. This instance selects all stored characters in the List whose “Salary” is greater than “70000” using the lambda function.
  • Then, pass the entire List “characters” and instance as an argument to the “filterCharacters()” function. This function stores the elements having a salary greater than “70000” in the “highSalaryCharacters” List.
  • Moreover, use the enhanced “for” loop to display each element of the “highSalaryCharacters” List.
  • After that, define a “filterCharacters()” method with the parameters of a “characters” list and “predicate” as an argument.
  • create a List named “filteredList” and use the enhanced “for” loop that traverses over the provided original list “characters”. 
  • Then, pass each element of the list to the custom-defined predicate(which is received as a parameter) “test()” method.
  • If the test returns “true”, that element of the “characters” list gets inserted into the “filteredList”. 
  • Once all “characters” List elements are tested, return the “filteredList” using the “return” keyword.

Entire Code:

import java.util.*;
import java.util.function.Predicate;

class CODCharacter {
private String Name;
private double Age;
private double Salary;

public CODCharacter(String name, double age, double salary) {
  this.Name = name;
  this.Age = age;
  this.Salary = salary;
}
public String getName() {
  return Name;
}
public double getAge() {
  return Age;
}
public double getSalary() {
  return Salary;
}
}

public class Filtering{
public static void main(String... args) {
  List<CODCharacter> characters = new ArrayList<>();
  characters.add(new CODCharacter("Francis - Dark Opulence", 33, 60000.0));
  characters.add(new CODCharacter("Yegor - NightLife", 28, 40000.0));
  characters.add(new CODCharacter("Demir - Lurking Dread", 37, 110000.0));
  characters.add(new CODCharacter("Foxtrot - Unseen Angel", 32, 80000.0));
  characters.add(new CODCharacter("Roland - Vinterblood", 32, 95000.0));
  // Predicate to filter characters with a salary above 70k
  Predicate<CODCharacter> highSalaryFilter = character -> character.getSalary() > 70000.0;
  List<CODCharacter> highSalaryCharacters = filterCharacters(characters, highSalaryFilter);

  System.out.println("Upcoming Characters with High Budget in Call of Duty:");
  for (CODCharacter elements : highSalaryCharacters) {
  System.out.println("\nName: " + elements.getName() + ", Age: " + elements.getAge() + ", Salary: $" + elements.getSalary());
  }
  }
private static List<CODCharacter> filterCharacters(List<CODCharacter> characters,
Predicate<CODCharacter> predicate) {
  List<CODCharacter> filteredList = new ArrayList<>();
  for (CODCharacter elements: characters) {
    if (predicate.test(elements)) {
    filteredList.add(elements);
    }
  }
  return filteredList;
}
}

The output for the above code shows that the List is now filtered according to the defined Predicate:

Method 3: Filter a List Using “Filter Interface” in Java

Filter Interface is also a functional interface and it uses the “logger” and “handler” to assign the target for the lambda function. The logger and its assigned handler in our case are targeted list and filter rules respectively. The lambda function is the one that applies the provided filter rules over the targeted list:

interface Filter<T, E> {
  boolean isMatched(T object, E text);
}
class FilterList<E> {
public <T> List<T> filterList(List<T> originalList, Filter<T, E> filter, E data)
{
List<T> filterList = new ArrayList<>();
for (int i = 0; i < original List.size(); i++) {
  T object = originalList.get(i);
  if (filter.isMatched(object, data)) {
  filterList.add(object);
  }
}
return filterList;
}
}

Now, let’s define a class to insert elements into the List, define the “main()” method, invoke the filtering method, and display a result:

class Employee {
private String name;
public Employee(String name) {
  setName(name);
}
public String getName() {
  return name;
}
public void setName(String name) {
  this.name = name;
}
public void displayInfo() {
  System.out.println("Filter Employee Database for '"+ name + "' Post.");
}
}
public class Filtering {
public static void main(String[] args) {
List<Employee> empList = new ArrayList<>();
empList.add(new Employee("Java Developer"));
empList.add(new Employee("Software Engineer"));
empList.add(new Employee("Senior Java Developer"));
empList.add(new Employee("Python Developer"));
Filter<Employee, String> filter = new Filter<Employee, String>() {
  public boolean isMatched(Employee object, String text) {
  return object.getName().contains(text);
  }
};
List<Employee> filteredEmpList = new FilterList<String>().filterList(empList, filter, "Java");
// Display the filtered list using the overridden method
for (int i = 0; i < filteredEmpList.size(); i++) {
  filteredEmpList.get(i).displayInfo();
}
}
}

The above code works like this:

  • First, create an interface “FilterInterface” having the logger and handler of “T” and “E”. Declare a boolean type “isMatched()” method and pass the “object” and “text” having the type of “T” and “E” as a parameter.
  • Next, define a class “FilterList” and pass the filter rule or handler “E” provided by the Filter interface to filter the List.
  • Inside it, use a “filterList” constructor that accepts the “originalList” logger, “filter” interface, and handler “data” as parameters.
  • Then, create an empty list named “filterList” and use the “for” loop that iterates till the length of “originalList”. Each element of the original List is then selected using the “get()” method and stored in a “T” type “object”. Now, the “if” statement is used and the “object” with the provided handler “data” are passed into the “isMatched()” method.
  • If that element gets matched with the filtering rule then the element gets added to the created “filterList”. Once all elements are checked, the “filterList” returns as our result.
  • Initially, create a class “Employee” that has a single class variable of “name” having the scope of “private”. 
  • The class contains a “getName()”, “setName()”, and “displayInfo()” method to get, set, and display the value of a “name” variable.
  • Now, define a “main()” method inside the “Filtering” class and declare a List named “empList”. Insert values into the List using the “add()” method and pass each value by invoking the “Employee” class constructor.
  • Moreover, declare a new instance “filter” for the “Filter” interface. Define the “isMatched()” method that accepts two parameters of “object” and “text”. 
  • This method selects the element “name” and matches it with the provided filtering rules/criteria “text”. The elements that satisfy the rules get returns by this method.
  • Finally, create an instance of the “FilterList” class. Then, Pass “empList” provided List, “filter” filtering rules, and “Java” keyword to be matched as constructor parameters. The result is stored in the “filteredEmpList” List.
  • Each element of this list is then selected using the “get()” method, and the “displayInfo()” method is applied to it. These methods display each filtered element on the console.

Output for the above code shows that the List is filtered successfully:

Method 4: Filter a List Using “Guava FluentIterable” Class in Java

The “FluentIterable” class provided by Guava works offers similar functionality to the Java 8 API Stream. It is “multiple-use” opposite to single-use Stream API and it can also implement Iterable. It offers “from()”, “transform()”, “limit”, and “toList()” methods to perform filtering or other operations more smoothly:

  • The “from()” method contains the original data on which the filtering or other operation needs to be done.
  • The “transform()” method accepts the predicate which stores the criteria or rules to filter. 
  • The “Limit()” method sets the limit on the data, like applying rules only on the first 10 elements and dropping the remaining elements.
  • The “toList” converts or stores the result in the desired collections like ArrayList, List, and many more.

Take a look at below code block for the practical implementation of the Guava “FluentIterable” class in Java:

import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import java.util.*;
//Importing the Required Guava and basic packages

public class Filtering {
public static void main(String[] args) {
  List<Artist> pickList = getMembers();
  Predicate<Artist> filterCriteria = member -> member.getRating() > 75;
  var filterResult = FluentIterable.from(pickList).filter(filterCriteria).toList();
  System.out.println("Picked Members:\n" + listToString(filterResult));
}

static List<Artist> getMembers() {
  List<Artist> artists = new ArrayList<>();
  artists.add(new Artist(86, "Morgan Freeman"));
  artists.add(new Artist(71, "Julia Roberts"));
  artists.add(new Artist(83, "Robin Williams"));
  artists.add(new Artist(79, "Denzel Washington"));
  artists.add(new Artist(67, "Salma Hayek"));
  return artists;
}

  static String listToString(List<Artist> allMembers) {
  StringBuilder result = new StringBuilder();
  for (Artist member: allMembers) {
  result.append(member.customDisplayer()).append("\n");
  }
  return result.toString();
}
}
class Artist {
  int rating;
  String name;
  public int getRating() {
  return rating;
  }
public Artist(int rating, String name) {
  this.name = name;
  this.rating = rating;
}
public String getName() {
  return name;
}
public String customDisplayer() {
  final StringBuilder outputs = new StringBuilder("Member { ");
  outputs.append("Name = '").append(name).append('\'');
  outputs.append(", Rating = ").append(rating);
  outputs.append(']');
  return outputs.toString();
}
}

The working of the above code is written below:

  • First, the required “base.Predicate” and “collect.FluentIterable” libraries are imported using the “import” keyword.
  • Next, define a “main()” method inside the custom-created “Filtering” class. Create a List “pickList” that contains the “Artist” class as a reference. It stores the results returned by the “getMembers()” method.
  • Create a “Predicate” named “filterCriteria” that uses the Lambda function to accept all elements that have a rating greater than “75”. This rating of each element is retrieved by invoking the getter “getRating()” method.
  • The “FluentIterable” class is used, and the values of “pickList” and “filterCriteria” are passed to its “from()” and “filter()” methods. The “toList()” method is also applied to convert the result into a List collection format.
  • The result is then inserted into a “filterResult” variable which is passed into the “ListToString()” method to convert into String format. After conversion, the filtered list is displayed on the console.
  • Now, define a “getMembers()” method which contains a List named “artists”. The values are inserted into the List using the “add()” method.
  • The values are generated or retrieved by passing the data into the “Artist” class constructor. Once all data is inserted, the list “artist” is returned by the method.
  • Moreover, another method “listToString()” that accepts a List “allMembers” as a parameter is created. Create an object for the “StringBuilder” class that traverses over the elements of an “allMembers” List. While traversing, the “customDisplayer()” method is applied to each element and a Line break is added after each element.
  • Then, that element is stored in a new String “result” created using “StringBuilder”. Finally, apply the “toString()” method on the “result” String and return it.
  • Now, create a class “Artist” that contains two default scoped attributes “rating” and “name”. The values are assigned to these attributes using the constructor and returned via “getRating()” and “getName()” methods. 
  • In the end, define a “customDisplayer()” method that creates a “final” type StringBuilder object named “outputs”. It creates an output String that uses the “append()” method to display the “Artist” class variable “name” and “rating” values. 
  • This object “outputs” is then returned by the method after passing through the “toString()” method.

The generated output shows the filtered version of the provided List:

This guide has explained all approaches that can be used to filter a List according to the desired requirements.

Conclusion

To filter a List in Java, the Stream API of Java 8 “filter()” method is commonly used. It uses the lambda expression to select and store the elements that satisfy the filtering criteria. It also provides “map()” and “collect()” methods to append or perform operations on the filtered data and to convert the data into any collection. The “Filter” interface uses the boolean type method with the concept of logger and handler to perform the filtering over the elements. 
The “Predicate” interface matches each element with defined filtering criteria. If the match returns true, that element gets stored in the filtered List. Last but Not Least, the Guava “FluentIterable” class provides “from()”, “transform()”, “limit”, and “toList()” methods. These methods provide full control over the filtering of List elements in a more structured manner. This guide has illustrated all techniques to filter a List in Java.