Lambda expressions in Java

Introduction

They have been around for some years now and yet I’ve heard very little about them. Back then, when Java 8 was new, I took a quick look at what was new. And Java 8 was introducing Lambda expressions, that you could use in your code. But what are these Lambda expressions (sometimes also referred to as Lambda functions)? Should you be afraid of them? Should we all use them? Let’s find out!

Lambda what?

Ok what are Lambda expression in Java then? The quickest and dirtiest explanation is, that they are another way to implement an interface inline. Let me show you what I mean with this example:

public class Test
{
    public static void main(String[] args)
    {
        Printable printableInt = (Integer i) -> System.out.println(i);
        printableInt.printContent(1337);
    }
}

interface Printable
{
    void printContent(E e);
}

Ok, so what this does is implementing the Interface and calling it’s method. Don’t worry, I’ll explain what a lambda expression has to look like in a second! 🙂

Now that you’ve seen an example (that might look confusing at first sight), let’s look at the process of building such lambda functions.

How to build lambda expressions

Interfaces need a concrete implementation, to be usable. That shouldn’t be too new. One way of creating such an implementation is to write a class that implements the interface’s methods:

public class ClassPrint implements Printable
{
    public void printContent(E e)
    {
        System.out.println("Class: " + e);
    }
}

The interface defines the structure of the class. The class itself represents the concrete functionality of the methods. You could have several classes that implement the interface and have different functionalities. This one simply outputs a variable and adds a string in front of it.

If you want to use the functionality of the class above, you’ll have to instantiate it. So you create an object of it, just to use it’s functionality. Wouldn’t it be nice if you could just use the functionality without having to create an object? Because all we want is to use it’s functionality, nothing else.

To do this, we’ll first remember the concept of inline declarations. It’s possible to declare variables like this:

int i = 1337;
String phrase = "Hello World!";

Okay, but can we do something like this?

inlineMethod = public void printContent(E e)
    {
        System.out.println("Class: " + e);
    }

Well, this won’t work, but it brings us one step closer to our lambda expression. To form one, perform the following steps:

// 1. Remove the Method's name
inlineMethod = public void (E e)
    {
        System.out.println("Class: " + e);
    }

Obviously you won’t need the method’s name, because you’ll simply use the variable name, we assign our method to.

// 2. Remove the access modifier
inlineMethod = void (E e)
    {
        System.out.println("Class: " + e);
    }

You won’t need that one either. Whoever can access the variable, can also call the Method, so you control accessibility with the variable’s access mod.

// 3. Remove the return type
inlineMethod = (E e)
    {
        System.out.println("Class: " + e);
    }

The Java compiler will find the right return type based on the interface. Now off to the last step:

// 4. Add -> just before the {}-block and add an ; at the end
inlineMethod = (E e) ->
    {
        System.out.println("Class: " + e);
    };

In method bodies that consist of one expression (like ours), you can omit the curly braces (just like if it were a single-lined if,else,for,… block):

inlineMethod = (E e) -> System.out.println("Class: " + e);

Now you’ll just have to assign a type to it. For now, let’s just assume that lambda expressions are an inline implementation of an interface. So the type of this expression is obviously the Interface it implements:

Printable inlineMethod = (Integer e) -> System.out.println("Class: " + e);

Please note that in this example at this stage the generic type has to be replaced with a concrete type, just as usual, however the expression can be shortened even more, because the compiler knows, what the type of the method parameter is, so this can be omitted:

Printable inlineMethod = (e) -> System.out.println("Class: " + e);

If, and only if, there is just one argument, like in this case, the parenthesis can be omitted as well, so the expression looks like this:

Printable inlineMethod = e -> System.out.println("Class: " + e);

But I like to keep both, the type(s) and the parenthesis, so it’s easier to understand, what’s going on.

The procedure of calling the lambda function is exactly the same, as it’d be with the class it came from: You just call the method, defined it the interface it implemented:

inlineMethod.printContent(1337);

Anonymous type, lambda expression, class?

Okay, so with this interface we’ll have some ways of implementing it:

public class Test
{
    public static void main(String[] args)
    {
        // Object
        Printable objectPrint = new ClassPrint<>();
        objectPrint.printContent(1337);

        // Anonymous type
        Printable anonPrint = new Printable()
        {
            @Override
            public void printContent(Integer e)
            {
                System.out.println("Anonymous type: " + e);
            }
        };
        anonPrint.printContent(1337);

        // Lambda expression
        Printable lambdaPrint = (Integer i) -> System.out.println("Lambda: " + i);
        lambdaPrint.printContent(1337);
    }
}

class ClassPrint implements Printable
{
    public void printContent(E e)
    {
        System.out.println("Class: " + e);
    }
}

interface Printable
{
    void printContent(E e);
}

As you can see, all three implement the same interface, but you can clearly see that the lambda expression is the shortest method.

Lambdas and return values

Obviously you can also return values from the method, implemented with the help of a lambda expression. You just have to remember one thing: If you use curly brackets in one-line-lambda expressions, you must use the return statement! If you don’t use the brackets, you are not allowed to use the return statement!

public class Test
{
    public static void main(String[] args)
    {
        // Lambda expression
        // No brackets, no return-statement!
        Printable lambdaPrint = (Integer i) -> "Lambda: " + i;

        // Brackets, must use return-statement!
        lambdaPrint = (Integer i) -> {
            return "Lambda: " + i;
        };
    }
}

interface Printable
{
    String printContent(E e);
}

Conclusion

Lambda expressions add functional programming to Java and they are a new way to implement Interfaces with one method inline. Instead of using anonymous inner types, you can now use lambda expressions to implement the exact functionality of a method defined by an interface.

Obviously all rules of polymorphism that apply to classes that implement an interface also apply to lambda expressions, as well as type inference.

To end this article, I’d like to show you a real-world application of lambda functions that comes in very handy, because it’s much shorter than the traditional way:

public class LambdaThread
{
    public static void main(String[] args)
    {
        try
        {
            Runnable runnableLambda = () -> System.out.println("Hello World!");
            Thread r = new Thread(runnableLambda);

            r.start();
            Thread.sleep(100);
            r.stop();
        }
        catch (Exception e){ }
    }
}

Tell us about your experiences with lambda expressions! Have you ever used them before? What do you think about them? Will you use them? 

comment-banner

13 thoughts on “Lambda expressions in Java

    1. Yes, you are right. And in my opinion it makes much more sense using them in C#, than in Java, because in in C# they are easier to use.

      Maybe I should update the post above and include the example of event handling 😀

      Like

  1. Lambda expressions are actually used a lot for inline event handling in C#.NET:

    For example:

    button.Clicked += (sender, e) => {
    };

    Liked by 1 person

  2. This isn’t a bad thing but I think the use of interfaces destroys the power of lambda functions. I mean obviously the compiler has to know what method to call and how to call it, but the need of an interface for each lambda function makes this whole thing so irrelevant in my eyes 😦
    It’s such a pity. They could have been so great but turned out to be this stupid to use …

    Liked by 2 people

    1. They should have come up with something better, anyway this way old code can still run on new versions of jre. so thats not bad however

      Liked by 1 person

Leave your two cents, comment here!

This site uses Akismet to reduce spam. Learn how your comment data is processed.