Functional Interfaces in Java 8

As mentioned earlier, functional interfaces are interfaces with only one Abstract Method. It’s a code template which is readily substituted for Lambda Expressions in Java.

1.Purpose

Functional Interfaces provides target types to Lambda Expressions and Method References.

1.1 The Annotation @FunctionalInterface

The Java Language and API has provided an annotation @FunctionalInterface to indicate that the given interface is a Functional Interface.

@FunctionalInterface
public interface MyInterface{
    public void oneMethodOnly(int test); 
} 

One must note that it is just an indicative notation and it is not compulsory to have this notation when you define a functional interface. Java compiler will consider any interface as a functional interface if it matches the definition of Functional Interface (Interface with only one abstract method) and put it as template for execution for lambda and method references.

2. Functional Interfaces in the Java 8 API.

Java 8 API comes with, out of the shelves interfaces which are essentially Functional Interfaces which can be used for many Lambda Expressions and Method References.Here is a detailed list of Java 8 Functional Interfaces in java.util.function package.

We shall see usage of three functional interfaces in this article: Predicate F, Consumer and Function Functional Interface which are most frequently use in our daily Java Programming patterns.

2.1 Predicate Functional Interface:

The functional interface Predicate<T> has at method with following signature:

boolean test(T t)

It’s natural to make it out that we will use this when we want to test some condition (Hence the name predicate). The test() function takes an object as an argument and returns boolean (whether test is true or not).

Lets see an example here:

  public List<String> filter(List<String> data, Predicate<String> filterPredicate) {
  List<String> result = new ArrayList<String>();
  for (String string : data) {

    if (filterPredicate.test(string)) {
      result.add(string);
      
    }
  }
  return result;
}

The function is quite easy to understand. If the predicate test is true, the elements of data list will be added to the result array list. Obvious question would be, how do we pass the predicate test as Predicate Functional Interface. Let’s see an example for the same:

List<String> resultStrs2 = stringFilter.filter(resultStrs, 
               (string) -> {
      return (string.charAt(0) == 'J');
    } );

The Java compiler will see that filter() function has Predicate<String> that is a second argument. The Lambda passed as argument in the second code snippet has the same signature of predicate functional interface. It has string as argument (Type of object as per Predicate<String> ) and returns boolean,in this case where the string starts with capital J. Logically speaking, here the if any String of array list passed as first argument in filter() function, it is added to the result array list if the predicate test passes and returns true.

There are various cases in daily Java programming were we can use a predicate test case for condition checking. And that is where the predicate functional interface will play role and useful for us.

2.2 Consumer Functional Interface:

This interface has a method called accept which takes a single argument and returns nothing. This can be used to do something with the values of the the object under considerations. Mainly to do something with it like, logging, printing, File IO, etc.

Lets see an extension of above example:

public List<String> filter(List<String> data, Predicate<String> filterPredicate, Consumer<String> consumer) {
    List<String> result = new ArrayList<String>();
    for (String string : data) {

      if (filterPredicate.test(string)) {
        result.add(string);
        consumer.accept(string);
      }
    }
    return result;
  }

Lets call both Predicate and Functional interfaces with Lambda Expression:

List<String> strList = Arrays.asList(new String[] { "Java", "Lamda", "", "JS", "cpp", "" });

    // write a code to filter blank string
    StringFilter stringFilter = new StringFilter();
    List<String> resultStrs = stringFilter.filter(strList, (string) -> {
      return (string.length() != 0);
    } , (string) -> {
      System.out.println(string);
    });

2.3 Function Functional Interface

Functional Interface is an interface which has apply function, that accepts one argument object and returns some argument object as per the generic definition Function<T,U> . Generally we use this function interface when we have to do some processing on the argument object and return the result in some other format or object type.

Lets see and example below. Here we want to map a list of Strings to list of integers which contains number of spaces in the corresponding strings in the arraylist. Let’s see how we can do this using a Function Functional Interface:

public static List<Integer> map(List<String> strings, Function<String, Integer> f) {
    List<Integer> spaces = new ArrayList<>();
    
    for (String string: strings) {
      spaces.add(f.apply(string));
    }
    return spaces;
  }

We shall call this in following way:

List<String> strings = Arrays.asList(new String[]{"Hello world java 8", "Hello world", "java 8"});
    
    Function<String, Integer> f = (str)->{return (str.length() - str.replaceAll(" ", "").length()); };
    
    List<Integer> counts = map(strings, f );
    for (Integer i: counts) {
      System.out.println(i);
    }

here the the Lambda for functional Interface is (extracted and reformatted for understanding):

(str)->{
      return (str.length() - str.replaceAll(" ", "")
                                                .length());
}

Here we have to calculate the lengths of string with spaces and lengths of string without spaces and then subtract first from latter, to get the number of strings and to get the total number of spaces in the strings.

This is how we can use Function Functional interfaces. Functional interfaces are mainly used when we have process and transform the data under consideration.

There are more such functional interfaces mentioned in the Java 8 API and used for really good utilities to make coding life better 🙂 .