How to filter a list in Java
A functionality that occurs in almost every application is the filtering of a list. The Java API before Java 8 does not yet contain an elegant way to filter a collection, so Guava and Apache Commons help out.
Filter the list with Java 8
With the new Java 8 Streams API and the use of lambda expressions, lists or other collections can be filtered quite elegantly. The functional interface java.util.function.Predicate is used for this. It contains only the test() method, which decides whether the predicate (a property) applies to the transferred object.
In the following example, a list of strings should be filtered by elements with the first letter “A”:
import java.util.*; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { List<String> names = Arrays.asList("Alex", "Amanda", "Emily", "Bob", "Jean"); List<String> filteredList = names.stream() .filter(new java.util.function.Predicate<String>() { @Override public boolean test(String s) { return s.startsWith("A"); } }).collect(Collectors.toList()); System.out.println(filteredList); } }
Output:
[Alex, Amanda][st_adsense]
First the list is converted into a stream. This stream is then filtered with the predicate and the stream is converted back into a list with the collect() method.
Thanks to the lambda notation of Java 8, the Predicate can also be passed as a simple function, which shortens the expression even more:
import java.util.*; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { List<String> names = Arrays.asList("Alex", "Amanda", "Emily", "Bob", "Jean"); List<String> filteredList = names.stream() .filter(s -> s.startsWith("A")) .collect(Collectors.toList()); System.out.println(filteredList); } }
Output:
[Alex, Amanda]
The lambda expression s -> s.startsWith("A")
makes the filtering even clearer.
Unfortunately, not all projects have been converted to Java 8 yet, which is why other solutions for Java 6 and Java 7 are presented here.
[st_adsense]
Filter the list with Google Guava
The Google Guava library also contains an interface com.google.common.base.Predicate with an apply() method that decides whether a property applies to the transferred object. Guava offers two ways to filter a list: com.google.common.collect.Iterables, a collection of useful methods, and com.google.common.collect.FluentIterable, (as the name suggests) a fluent interface that is similar to the Java 8 Streams API offers methods that can be applied to a collection one after the other.
Guava Iterables
In the first example, Iterables is supposed to filter a list of strings for elements beginning with the letter “A”:
List<String> names = Arrays.asList("Alex", "Amanda", "Emily", "Bob", "Jean"); Iterable<String> filteredIterable = Iterables.filter(names, new com.google.common.base.Predicate<String>() { @Override public boolean apply(String s) { return s.startsWith("A"); } }); List<String> filteredList = Lists.newArrayList(filteredIterable); System.out.println(filteredList);
Output:
[Alex, Amanda]
A small disadvantage of this solution is that Iterables.filter()
does not return a list, but an Iterable object that must first be converted into a list again.
[st_adsense]
Guava FluentIterable
Perhaps a slightly more elegant solution is to use FluentIterable, which as mentioned earlier is not different than Java 8 Streams:
List<String> names = Arrays.asList("Alex", "Amanda", "Emily", "Bob", "Jean"); List<String> filteredList = FluentIterable.from(names) .filter(new com.google.common.base.Predicate<String>() { @Override public boolean apply(String s) { return s.startsWith("A"); } }).toList(); System.out.println(filteredList);
Output:
[Alex, Amanda]
The from() method creates a FluentIterable from the list, which is filtered and then converted back into a list.
Filter the list with Apache Commons Collections
Another possibility is offered by the CollectionUtils class of the Apache Commons Collections. This library also contains a predicate class: org.apache.commons.collections4.Predicate with a test method evaluate(), which decides whether a property applies to the transferred object.
The CollectionUtils.filter() method can be used to filter a list of strings by elements beginning with the letter “A”, which accepts the collection and the Predicate object to be filtered.
List<String> names = Arrays.asList("Alex", "Amanda", "Emily", "Bob", "Jean"); ArrayList<String> filteredList = new ArrayList<>(names); CollectionUtils.filter(filteredList, new Predicate<String>() { @Override public boolean evaluate(String s) { return s.startsWith("A"); } }); System.out.println(filteredList);
Output:
[Alex, Amanda]
It should be noted that the method changes the transferred list. Therefore a copy of the list is created first, which is then passed to CollectionUtils.filter().
[st_adsense]
A pure Java solution for filtering a list
If you don’t want to add a utility library like Apache Commons or Google Guava to your project, you can of course write a simple method to filter a list yourself. The best way is to create a predicate interface. This should be similar to Java 8, so that it can be easily replaced when you change your project to Java 8 later:
public interface Predicate<T> { boolean test(T t); }
This interface is now used to write a method filterList():
public static <T> List<T> filterList(List<T> list, Predicate<T> predicate) { List<T> filtered = new ArrayList<>(); for (T element:list){ if(predicate.test(element)){ filtered.add(element); } } return filtered; }
This method can now be called similar to the above examples with the list and a predicate:
List<String> names = Arrays.asList("Alex", "Amanda", "Emily", "Bob", "Jean"); List<String> filteredList = filterList(names, new Predicate<String>() { @Override public boolean test(String s) { return s.startsWith("A"); } }); System.out.println(filteredList);
Output:
[Alex, Amanda][st_adsense]