Filter a List by Any Matching Field
Java 8 introduced the powerful Stream API
, making it easier to process collections in a functional programming style. Let us delve into understanding how to filter a list in Java by any matching field.
1. Using the Stream.filter() Method
The Stream.filter() method allows us to filter elements in a collection based on a given predicate. Here’s an example of filtering a list of objects based on a specific field.
import java.util.*; import java.util.stream.Collectors; class Employee { private String name; private String department; private int age; public Employee(String name, String department, int age) { this.name = name; this.department = department; this.age = age; } public String getName() { return name; } public String getDepartment() { return department; } public int getAge() { return age; } @Override public String toString() { return "Employee{name='" + name + "', department='" + department + "', age=" + age + "}"; } } public class FilterExample { public static void main(String[] args) { List<Employee> employees = Arrays.asList( new Employee("Alice", "HR", 30), new Employee("Bob", "IT", 25), new Employee("Charlie", "Finance", 28), new Employee("Diana", "IT", 35) ); // Filter employees by department "IT" List<Employee> filteredEmployees = employees.stream() .filter(e -> "IT".equals(e.getDepartment())) .collect(Collectors.toList()); filteredEmployees.forEach(System.out::println); } }
1.1 Code explanation and output
The code defines a simple Java application that demonstrates how to filter a list of objects using the Stream
API introduced in Java 8. The Employee
class represents an employee with three fields: name
, department
, and age
. It includes a constructor for initializing these fields, getter methods for accessing their values, and an overridden toString()
method to provide a readable string representation of the object.
In the FilterExample
class, the main
method creates a list of Employee
objects using Arrays.asList()
. This list contains four employees with different names, departments, and ages. The program then uses the Stream.filter()
method to filter the list of employees and retain only those who belong to the “IT” department.
The filtering operation is performed using a lambda expression: e -> "IT".equals(e.getDepartment())
. This predicate checks if the department
field of an Employee
object matches the string “IT”. The filtered employees are collected into a new list using Collectors.toList()
.
Finally, the program iterates through the filtered list using the forEach
method and prints each Employee
object to the console. The output consists of the details of all employees whose department is “IT”.
Employee{name='Bob', department='IT', age=25} Employee{name='Diana', department='IT', age=35}
2. Creating a String Representation for Filtering
Sometimes, we may want to filter based on multiple fields by combining them into a single-string representation. This approach simplifies the predicate logic.
public class FilterExample { public static void main(String[] args) { List<Employee> employees = Arrays.asList( new Employee("Alice", "HR", 30), new Employee("Bob", "IT", 25), new Employee("Charlie", "Finance", 28), new Employee("Diana", "IT", 35) ); // Filter employees with the substring "IT" in their string representation List<Employee> filteredEmployees = employees.stream() .filter(e -> (e.getName() + " " + e.getDepartment()).toLowerCase().contains("it")) .collect(Collectors.toList()); filteredEmployees.forEach(System.out::println); } }
2.1 Code explanation and output
The provided code is a Java program that filters a list of employees based on whether a specified substring (“IT”) exists in a concatenated string representation of their name and department. The program leverages the Stream
API introduced in Java 8.
Inside the main
method, a list of Employee
objects is created using Arrays.asList()
. Each Employee
object represents an employee with attributes like name, department, and age. In this example, the list includes four employees with different values for these attributes.
The filtering operation is performed on this list using the Stream.filter()
method. For each employee in the list, the filter
method combines the name
and department
fields into a single string using e.getName() + " " + e.getDepartment()
. This combined string is then converted to lowercase using the toLowerCase()
method to make the search case-insensitive.
The .contains("it")
method checks if the combined string contains the substring “it”. If it does, the employee is included in the filtered result. The filtered employees are then collected into a new list using Collectors.toList()
.
Finally, the forEach
method is used to iterate over the filtered list, and the System.out.println
statement prints each matching Employee
object to the console. The output consists of employees whose name or department includes the substring “IT”, regardless of case.
Employee{name='Bob', department='IT', age=25} Employee{name='Diana', department='IT', age=35}
3. Creating a General Full-Text Search Method
To make filtering more generic, we can create a method that accepts a search term and matches it against all fields of an object.
public class FilterExample { public static void main(String[] args) { List<Employee> employees = Arrays.asList( new Employee("Alice", "HR", 30), new Employee("Bob", "IT", 25), new Employee("Charlie", "Finance", 28), new Employee("Diana", "IT", 35) ); // General full-text search String searchTerm = "Bob"; List<Employee> filteredEmployees = employees.stream() .filter(e -> fullTextSearch(e, searchTerm)) .collect(Collectors.toList()); filteredEmployees.forEach(System.out::println); } private static boolean fullTextSearch(Employee employee, String term) { String allFields = String.format("%s %s %d", employee.getName(), employee.getDepartment(), employee.getAge()); return allFields.toLowerCase().contains(term.toLowerCase()); } }
3.1 Code explanation and output
The provided code is a Java program that demonstrates how to implement a general full-text search on a list of objects. It allows filtering of objects based on whether a specified search term matches any field value of the object, using Java 8’s Stream
API.
In the main
method, a list of Employee
objects is created using Arrays.asList()
. Each Employee
object represents an individual with attributes like name
, department
, and age
. The list contains four employees with diverse attributes.
The program defines a search term, searchTerm
, with the value “Bob”. The goal is to find employees whose details include this term in any field (e.g., name, department, or age). The Stream.filter()
method is used to process the list of employees. It calls a helper method, fullTextSearch
, for each employee.
The fullTextSearch
method takes an Employee
object and a search term as input. It concatenates all the fields of the employee into a single string using String.format()
, creating a unified text representation of the employee. This string is converted to lowercase to ensure the search is case-insensitive.
The method checks if the search term (also converted to lowercase) is contained within the concatenated string using .contains()
. If the term is found, the method returns true
, indicating that the employee should be included in the filtered results.
The filtered list of employees is collected using Collectors.toList()
and printed to the console using forEach
. The output consists of all employees whose name, department, or age matches the search term.
Employee{name='Bob', department='IT', age=25}
4. Conclusion
Java 8’s Stream
API provides powerful tools for filtering collections. By using methods like Stream.filter()
, creating string representations, or implementing general full-text search methods, we can easily filter lists based on any matching field. These approaches help make code more readable and maintainable.