Functional Interfaces And Lambda Expressions in Java

Praveen Alex Mathew
4 min readMay 1, 2019

--

Java does not provide function as a primitive data type. Storing a function in a variable and passing it around can be achieved using a SAM<Single Abstract Method> interface.

passing a function as a parameter in Java

In the above snippet, the function getPower in the main class is oblivious to the logic require to compute the power of the number. A function calulatePower is passed to the getPower method by the caller function.

Java 8 introduces a new Annotation @FunctionalInterface which enforce the interface to contain one and only one abstract method.

A functional interface is a interface that may or may not have default methods but has one and only one abstract method.

The functional interface such as the Runnable interface has been around since Java 1, however it was only in Java 7 that Anonymous Classes were allowed in java.

Without Anonymous Class
With Anonymous Classes

With Java 7’s Anonymous classes, the developers needn’t come up with names for the single implementation of the interface which wont be used more than once. However, passing the anonymous class tends to be verbose as you can see.

Java 8 brought in lambda expressions or nameless functions that solved the issue. Turns out the functional interface has only a single abstract method. The function mentioned in the body of the lambda expression overrides the abstract method and creates an anonymous implementation of the functional interface.

With Lambda Expression

A lambda function is an expression with just the function body and the parameter list if applicable.

The lambda expressions are used extensively in Java streams.

Predefined Functional Interfaces in Java

Functional Interfaces aid in lazy evaluation of code. The code defined in the functional interface is not evaluated unless explicitly required. This helps in running long side-process, usually I/O, outside the normal execution.

For instance, if we plan to get or push our data to a REST endpoint via HTTP calls, given the condition, the following interfaces can be helpful

Runnable

A Runnable takes in no input and returns no output. It is apt for performing lengthy side effect operations that have no impact on the actual flow of execution.

For instance, if we had to perform a said action while executing the business logic if certain conditions are met, we can have the action in a Runnable.

static void businessLogic(Runnable action){
boolean actionNeedsToBePerformed = false;

/*
business logic comes here along with
the decision to perform the action
*/

if(actionNeedsToBePerformed){
action.run();
}

/*
Remainder code
*/
}
public static void main() {
String endpoint = "https://myapp-counter-endpoint.com";
Runnable counterIncrementor = new Runnable() {
void run() {
makeHttpPOSTCall(endpoint)
}
}
businessLogic(counterIncrementor);
}

Thus the businessLogic method need not be aware of the implementation of the action. Nor is the lengthy action operation executed unless required.

Official Dos: Runnable.html

Supplier<T>

Unlike the Runnable, Supplier returns an output. However, it takes in no input. The interface can be invoked to create the data when required. The data type of the output returned by the Supplier is specified by the Generic T.

For instance if we had to get information from a third party, we could the wrap logic to get the data in a Supplier and send it to the businessLogic function.

static void businessLogic(Supplier temperatureGetter){
boolean actionNeedsToBePerformed = false;
float temperature = 0;
/*
business logic comes here along with
the decision to perform the action
*/

if(actionNeedsToBePerformed){
temperature = temperatureGetter.get();
}

/*
Remainder code
*/
}
public static void main() {
String endpoint = "https://timely-weather-data.com";
Supplier<Float> temperatureGetter = new Supplier() {
float get() {
WeatherData data = makeHttpGETCall(endpoint);
return data.getTemperature();
}
}
businessLogic(temperatureGetter);
}

In the above example, the value of temperature is called only when needed. Also if the value is not needed in the flow of execution, it is never called. Moreover, the businessLogic method is not aware of the logic to get the data and so the changes to the latter wont affect the former.

Official Docs: Supplier.html

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Praveen Alex Mathew
Praveen Alex Mathew

Written by Praveen Alex Mathew

Software Developer. Masters in Computer Science @Arizona State University. https://praveenmathew92.github.io/

No responses yet

Write a response