Java Lambda Expressions

Kasun Dharmadasa
4 min readDec 29, 2018

--

Lambda expressions are known to be the biggest feature introduced with Java 8. This was the Java’s first step to Functional Programming.

As most of us are used to write code using Object Oriented Programming, it’s a bit hard at first to understand these Lambda expressions. We are used to using functions only after defining them inside a class, create an object of the class to call the method. But that’s going to change now.

Understanding the Lambda Syntax

Consider a variable defined in Java.

Object myObject

We usually use them to assign an object reference to it.

Object myObject = new Object();

Now, instead of assigning a reference of an object to the variable, what will happen if we assign a method to it?

Consider the following function

public void myFunction(String s1, String s2) {
System.out.println("String1 = " + s1 + " and String2 = " + s2);
}

Let’s assign the above method definition to a variable. For simplicity, let’s just focus on the lambda expression syntax. We can later investigate more on the type of the variable that it needs to be assigned. Till then, I have used a dummy variable name “aBlockOfCode”

aBlockOfCode = public void myFunction(String s1) {
System.out.println("Hi " + s1);
}

Since now the method has been assigned to the variable, there are several details that we can omit. The modifier “public” will be useless as the visibility of this method will be decided by the access modifiers defined for the variable (not for the function).

We can also remove the function name (myFunction) as nobody else is going to use this function with its name (We can reference it with the variable name instead).

After removing the above two parts now the code looks like this

aBlockOfCode = void (String s1) {
System.out.println("Hi " + s1);
}

What else can we omit?

The Java 8 compiler is now much smart. It doesn’t require the method return type. The Java 8 compiler can detect the return type by inspecting the method body. Also, it doesn’t require the type of the method argument. So, we can reduce the above expression further

aBlockOfCode = (s1) {
System.out.println("Hi " + s1);
}

One more additional detail is required before calling this as a lambda expression. There needs to be a “->” sign after the input variable declaration. Our final lambda expression will be

aBlockOfCode = (s1) -> {
System.out.println("Hi " + s1);
}

If there is only one line in the body of the method, we can remove the curly brackets as well

Finally, the simplified lambda expression for our myFunction method will be as follows.

aBlockOfCode = s1 -> System.out.println("Hi " + s1);

As you can see, the lambda expressions have made our code much smaller and simpler.

More examples on Lambda Expressions

a. If there are no input parameters the, the syntax would be

aBlockOfCode = () -> System.out.println("Hello World");

b. If there needs to be return statement the lambda expression can be written as

aBlockOfCode = (s1, s2) -> {
String myString = "String1 = " + s1 + " and String2 = " + s2;
return myString;
}

Now you may have some understanding about the syntax of a lambda expression. Let’s dig into the left side of the assignment expression (what is the actual type of the variable “aBlockOfCode”?)

Functional Interfaces

Functional interfaces are defined as interfaces that are having only one abstract method. In Java 8, they are annotated by @FunctionalInterface annotation. A sample Functional Interface can be created as follows.

@FunctionalInterface
public interface SampleFunctionalInterface {

abstract String foo(String s1);
}

Turns out these type of Functional Interfaces can be used to assign lambda expression. If we look back at our previous sample lambda expression, we can now do the actual assignment to our SampleFunctionalInterface.

Running the above code will provide the following output

"Hi Alice"

Now we understand that we need a Functional Interface to write a lambda expression. But,

Do I have to create a new functional interface every time I write a Lambda expression?

Fortunately, NO.

Java 8 has a built in collection of Functional Interfaces that can be used to write most of the Lambda expressions.

Support from Java

java.util.function package in Java packs a list of Functional Interfaces out of the box. As it turns out there is already a Functional Interface provided by Java that acts similar to our “SampleFunctionalInterface”.

The Consumer<T> interface in java.util.function package takes up a single argument of any given type and provides a void method that consumes the provided argument.

@FunctionalInterface
public interface Consumer<T> {
void accept(T var1);
}

We can use this Consumer<T> interface to rewrite our first Lambda expression as follows.

Another such example is the java.util.function.Function<T,R> interface

@FunctionalInterface
public interface Function<T, R> {
R apply(T var1);
}

Using this interface we can write a lambda expression that takes up one argument of any type and returns a value of any type.

Let’s create a lambda expression that takes a String as an argument and returns the length of the provided String (“MyString”).

The output of the above code will print “8” to the console.

The Purpose

The introduction of lambda expressions paved the way for Functional Programming by passing functions as arguments for another function. Java 8 introduced a stream package that improved the collection libraries in Java with new concurrency features that boosted the performance in multi-core environments.

References

[1] https://javabrains.io/courses/java_lambdabasics/

[2] https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/Lambda-QuickStart/index.html

--

--