Function

The Function interface can encapsulate an operation, and allows chaining functions by using the compose and andThen methods.

Function<String, Integer> function;
Integer result;

// Function initialization is skipped

result = function.apply("abc");

Chaining Functions

The interface contains default methods to chain operations through function composition:

Function<String, Integer> function1;
Function<Integer, String> function2;
Function<Integer, String> firstThenSecond;
Function<Integer, String> secondThenFirst;

// Function initialization is skipped

// Apply function 1 then function 2
firstThenSecond= function1.andThen(function2);

// Apply function 2 then function 1
secondThenFirst = function1.compose(function2);

Mapping Methods

Any method can be used as a function.

In this case an abstract method will be used as a strategy, to support the template method pattern. This method is as follows:

protected abstract Iterable<T> onRead(final T sample);

Then we have another method ready to make use of a function with the same erasure:

private final <I, O> Iterable<O> read(final I sample, final Function<I, O> strategy)
{
   // Additional operations goes here
   return strategy.apply(sample);
}

And now this can be used like this:

public final read(final I sample) {
   return read(input, this::onRead);
}

While at first this may be overly complex, take not that in a real application the second method would encapsulate complex operations, allowing the programmer to just change the particulars of the read operation:

public final read1(final I sample) {
   return read(input, this::onRead1);
}

public final read2(final I sample) {
   return read(input, this::onRead2);
}

public final read3(final I sample) {
   return read(input, this::onRead3);
}

Extensions

The JDK includes a BiFunction, which supports two arguments as input, and a few extensions for numeric primitives, and a binary operator which takes two instances of the same type.

Last updated