Java 8 Streams API: Filters

Datetime:2016-08-23 00:36:02          Topic: Java8           Share

Using the Streams API means thinking of your Collections in a different way. We looked at mapping from one type to another in the last posthere but in this tutorial I want to show how we take our Stream and only deal with certain values. In this example we want to only deal with Customers with a high credit limit. We do it by applying a filter. Here is all the code to get this to work:

import java.util.Arrays;
import java.util.Collection;

public class Tutorial1 {

	public static void main(final String[] args) {
		
		// Create a list.
		final Collection<Customer> customers = Arrays.asList(
				new Customer("Alpha Ltd", 1000), 
				new Customer("Bravo Ltd", 400),
				new Customer("Charlie Ltd", 5000),
				new Customer("Delta Ltd", 15000)
				);
		
		// Get list of customers with credit limit greater than 1000:
		customers.stream()
					.filter(customer -> customer.creditLimit > 1000)
					.forEach(System.out::println);
	}
}

class Customer {
	final String name;
	final int creditLimit;
	
	Customer(String name, int creditLimit) {
		this.name = name;
		this.creditLimit = creditLimit;
	}

	public String toString() {
		return "Customer [name=" + name + ", creditLimit=" 
                   + creditLimit + "]";
	}

}

As in the last tutorial we have a Collection of Customers. To work with it we go straight to a Stream by calling the ‘stream()’ method:

// Get list of customers with credit limit greater than 1000:
customers.stream()

This is the same way we might go from working with an Object array to a Collection to make use of its OO capabilities. Here we go from OO to a more FP (functional programming) capability.

Next we filter out anything that doesn’t meet the requirements:

// Get list of customers with credit limit greater than 1000:
customers.stream()
    .filter(customer -> customer.creditLimit > 1000)

The precise term for the boolean condition used is a Predicate. We could have declared it separately, as shown below:

Predicate<Customer> hasHighCredit = customer -> 
          customer.creditLimit > 1000;

// Get list of customers with credit limit greater than 1000:
customers.stream()
    .filter(hasHighCredit)

Finally we declare what we want to do with each Customer meeting our criteria by passing the System.out.println call to the forEach function.

// Get list of customers with credit limit greater than 1000:
customers.stream()
    .filter(hasHighCredit)
    .filter(System.out::println);

On its own its quite useful but filter should be seen as one of the building blocks when using Streams, just like map. It is when they are put together that complex logic from pre-Java 8 can be made simpler. The only issue is the learning curve but it is worth it.





About List