Java 8 Lambda Expressions by Examples

Java 8 lambda

Lambda

Ever since I heard Java 8 is going to support lambda expressions (aka closures), I was very enthusiastic to spice my code with such a decent and concise functional element. Most developers extensively use Anonymous Inner Classes for event handlers, comparators, basic thread/runnable implementations, etc. and overburden the logic with unnecessary scaffolding, even a very simple piece of code seems complex and unwieldy. Java now has added Lambda expressions as part of language syntax that helps solve similar problems in a very elegant manner.

It enables developers to encapsulate a single unit of behavior and pass it to other code. It’s like syntactic sugar for an anonymous class (with one method whose type is inferred) and is an object-less method. I prefer avoiding extensive theoretical material in this post, but before moving further towards understanding the syntax, structure and examples of lambdas, there is an important concept that needs attention.

Functional Interface

A Functional Interface (aka Single Abstract Method type or SAM) is any interface that contains only one abstract method. But it may contain some static or/and default methods. java.lang.Runnable is an example of a Functional Interface, as it has only one run() method, which is abstract. Similarly ActionListener interface is also a functional interface. Following is an example of user defined functional interface.

interface Worker() {

    boolean doWork();
};

Have a look at another templatized functional interface example:

interface Operator {

    TYPE operate(TYPE operand1, TYPE operand2);
}

That’s it, as it’s a normal interface that has just one abstract method. Although there is more to talk on functional interface specially java 8’s provided package
java.util.function and @FunctionalInterface annotation but for now just focus on lambdas. I will cover these topics in detail in a separate post.

Lambda Expressions

Lambda expressions, also known as closures, are anonymous methods that provide developers with a simple and compact means for representing behavior as data.

- Brian Goetz, Specification Lead for JSR 335

To easily understand the syntax of a lambda expression we first take a look at conventional Anonymous Inner Class.

new Runnable() {

    public void run() {

        performWork();
    }
};

Lambda expressions provide the remedy for clumsiness of an Anonymous Inner Class and convert above five lines into a single line like.

() -> performWork();

Syntax and Structure

So, standard syntax of lambda is as follows:

() -> some expression

Or

(arguments) -> { body just like function }

A lambda expression consists of the following three parts:

  1. A comma-separated list of formal parameters enclosed in parentheses.
    // Taking two integers and returning their sum
    (int x, int y) -> x + y
    
    // lambda expression with single integer argument that returns its next integer value
    (int x) -> { return x + 1; }
    

    You can omit the datatype of the parameters in a lambda expression.

    // same lambdas without argument types
    (x, y) -> x + y
    
    (x) -> { return x + 1; }
    

    In addition, you can omit the parentheses if there is only one parameter.

    // single argument lambda without parentheses
    x -> { return x + 1; }
    
  2. The arrow token, ->
    //Lambda taking no argument and returning a constant integer vale, 92
    () -> 92
    
    // taking a string as an argument and printing that on console
    (String s) -> { System.out.println(s); }
    
  3. A body, which consists of a single expression or statement block. In the expression form, the body is simply evaluated and returned.
    // for single statement body, no need to use braces and the return statement
    x -> x + 1
    
    // simple lambda with void return type
    () -> System.out.println(“Hello World!”)
    

    In the block form, the body is evaluated like a method body and a return statement returns control to the caller of the anonymous method.

OK, we spend enough on syntax of lambda, let’s move to some real examples

Examples of Lambda Expressions

To easily understand the lambda expressions, let’s start with some basic comparative examples with anonymous inner class. In the first example, we will see the use of lambda Comparator interface implementation. Assume we have a Person class with name property, and we have constructed an array of Person objects, named persons.

Arrays.sort(persons, new Comparator() {

    @Override
    public int compare(Person first, Person second) {

        return first.getName().compareTo(second.getName());
    }
});

// it’s a standard sort but interestingly rather than passing Comparator object, it’s taking a lambda expression
Arrays.sort(persons,(first, second) -> first.getName().compareTo(second.getName()));

Notice that five lines of code turned into a single line, that’s the beauty of lambda over anonymous inner class. Now let’s look at another example of Runnable implementation.

Runnable printer = new Runnable() {

    @Override
    public void run() {

        System.out.println("Hello, I’m inside runnable class...");
    }
};

printer.run();

printer = () -> System.out.println("Hello, I’m inside runnable lambda...");

printer.run();

Writing lambda expression for user defined functional interface is also very simple and easy. Following example uses Operator custom interface and stores lambda expression in a reference variable for the sake of reusability;

Operator addition = (op1, op2) -> op1 + op2;

System.out.println("Addition result: " + addition.operate(2, 3));

For further understanding, there is another example of lambda expression with statement block.

interface GenericOperator {

    TYPE operate(TYPE ... operands);
}

//lambda expression with statement block
GenericOperator multiply = numbers -> {

    int result = 0;

    for(int num : numbers)
        result *= num;

    return result;
};

System.out.println("Multiplication result: " + multiply.operate(2,3,4));

As demonstrated above, the block is just like a normal function block and lambdas are functional elements similar to methods, but with higher significance.

When to use Lambda expression

Lambda is not actually the replacement of anonymous inner class but a batter way to implement the single abstract method type. Both of them has their significance and are intended to use in their specific scenarios.

  • Lambda expression are meant to implement a single unit of behavior that is intended to pass to other code.
  • Its usable when just simple instance of functional interface is desired, without having a type, constructor and related stuff.

On the other hand anonymous inner class is used when new fields/functionality is required.

Lambda expression and Anonymous inner class

  • Anonymous class introduce next level of scoping, whereas lambda expression is just like an enclosing environment. New variable with same name, as in its super scope, is allowed in inner class, whereas lambda throw error and don’t allow that. Because it don’t introduce next level of scoping, local variable/field/method are directly accessible from enclosing scope.
  • Anonymous class resolve this keyword to their own object, though lambda resolves it to enclosing class where it’s written. To access variables inside lambda from enclosing class, you can use this.
  • However, like anonymous class, lambda expression can only access local variable of the enclosing block that is final or effectively final. Access to non-final variable throws an error just like anonymous class.
  • Serialization of lambda expression is allowed only if its parameter(s) and return type/target type are Serializable. Whereas its serialization is highly discouraged like anonymous class.
  • Lambda expression is compiled as a private method of enclosing class. invokedynamic is used to bind methods dynamically, that was introduced in java 7.

Source Code

An IntelliJ project containing the source files for the examples covered in the post.
Download Source

 

Where to go next: Other interesting features of Java 8

 

2 thoughts on “Java 8 Lambda Expressions by Examples

  1. Pingback: JavaPins

Leave a Reply