# Filtering a List

In this section we’ll introduce the example that will serve us as guide for the remainder of the chapter.

## Number filtering

Assume that we have a `List<Integer>` with some elements and that we need to filter these data and only return numbers that are below a certain maximum (let’s assume `10` is our limit), like this:

 In this example we are using `Integer`, but the same applies to any other type of object.
 In the example code run the `JavaListExampleApp`
``````// our input list of numbers
List<Integer> numbers = Arrays.asList(1, 2, 3, 10, 11, 12, 0);

// we'll store our filtered results in this list
List<Integer> filtered = new ArrayList<>();

// filter the list and allow only numbers that are less than 10
for (Integer number : numbers) {
if (number < 10) {
filtered.add(number);
}
}

// print out the filtered list
for (Integer number : filtered) {
System.out.println(number);
}``````

Output:

``````1
2
3
0``````

In this example our filter is inside the first `for` loop, where we check for each `number` in our list whether it passes or not the criteria we have, in our case, we only allow numbers that are less than `10`.

## Changing the filter

Now, what happens if we’re asked to implement multiple filters? For example, what if we also need to filter the list to allow only numbers greater than 5?

We could of course, change our filter to be:

``````//...
for (Integer number : numbers) {
if (number > 5) {
filtered.add(number);
}
}
//...``````

However, this isn’t very generic and depending the case it might not be what we want to do.

For example, what happens if we need to filter using logic that we don’t control? Like in the case where we provide a code library and the users of our library want to define how to filter the data.

This now sounds like we’re defining a contract between us and others, and of course, the easiest approach to do this is to provide an `interface` that defines this contract of what a `Filter` is.

In our case, a filter receives an element (in our example an `Integer`) and it should return `true` if the element should be included, and `false` otherwise. This interface can be modelled like this:

``````public interface Filter<E> {
boolean filter(E element);
}``````

## Greater than 5 filter

Now, for the second filter mentioned above, we can define an implementation of our `Filter` class that filters numbers and only allows numbers greater than 5, as such:

``````public class GreaterThanFiveFilter implements Filter<Integer> {

@Override
public boolean filter(Integer element) {
if (element > 5) {
return true;
}
return false;
}

}``````

## Filtering numbers using a `Filter`

Once we have the implementation of `Filter` that we want to use, we can change our original code to use it, for example:

 In the example code run the `JavaListExampleWithFilterApp`
``````public static void main(String[] args) {
// our input list of numbers
List<Integer> numbers = Arrays.asList(1, 2, 3, 10, 11, 12, 0);

// get the filter we want to use
Filter<Integer> filterToUse = new GreaterThanFiveFilter();

// call our new `filterNumbers` static method to do the filtering
List<Integer> filtered = filterNumbers(numbers, filterToUse);

// print out the filtered list
for (Integer number : filtered) {
System.out.println(number);
}
}

private static List<Integer> filterNumbers(List<Integer> numbers, Filter<Integer> filterToUse) {
List<Integer> filtered = new ArrayList<>();
// filter the list using the provided `filterToUse`
for (Integer number : numbers) {
if (filterToUse.filter(number)) {
filtered.add(number);
}
}
return filtered;
}``````

Output:

``````10
11
12``````

## The good and the bad

The good thing with our new approach is that we now have a new method called `filterNumbers` that receives the list of numbers we want to filter and it can also receive any implementation of our `Filter` interface to perform the filtering.

In this sense, we can provide any type of filter we want (like, finding numbers lower than, greater than or equal to a given number, or anything we want really).

The bad thing is that we need to create a whole new class per filter we want to apply. This is very verbose, for example, we already have a `GreaterThanFiveFilter` class, and if we want to implement other filters, like in the first example above, we’d need to create more classes.

This is one place where anonymous classes and, more recently, lambdas can help as we’ll see in the next 2 sections.

 This of course isn’t really a major problem, but it isn’t great either. Our example is very basic and only meant to introduce the concepts in the next sections. This is to highlight the issue we’re trying to solve.