10. Lambda Expressions
Programming Project 2021/22

10.2. What is a Lambda Expression?

Definition

Lambda expressions provide a shorter way of writing an implementation of a method for later. They are also known as closures or anonymous methods.

This feature was introduced in Java 8 to replace the "vertical problem" of anonymous classes, using a lots of code lines to only represent a single call to a method, for example.

Runnable r = new Runnable() {
  public void run() {
    System.out.println("Howdy, world!");
  }
};
Runnable r = () -> System.out.println("Howdy, world!");

Source

Syntax of lambda expressions

  • The syntax of a lambda expression is:

    (formal parameter list) -> { expression or statements }

    (x, y) -> x + y
    (x, y) -> { 
      return x + y;
    } 
    (int x, int y) -> { 
      return x + y;
    } 

Parameter list

A comma-separated list of formal parameters that match the formal parameters of the single method in a functional interface

  • Specifying the parameter types is optional (they can be inferred from the context).

    (x, y) -> x + y
  • The parameter list must be enclosed within parentheses except when a single parameter is specified without its type.

    (int x, int y) -> x + y
    (int x) -> x * 2
    x -> x * 2
  • If there are no parameters, empty parentheses must be specified.

    () -> System.out.println("Hello lambdas")

Source

Lambda body

The lambda body has a result that must be one of the following:

  • void, if the functional interface method result is void
  • A Java type, primitive type, or reference type that is the same as the return type of the functional interface method

The lambda body result is returned according to one of the following options.

  • If a single expression is used, the expression value is returned.

    (int x, int y) -> x + y
  • If a statement block is used and the method has a return type, a return statement must be used.

    (int x, int y) -> {
      x++;
      y++;
      return x + y;
    }

If the functional interface method result is void, return statements are optional.

When a lambda expression is invoked, the code in the lambda body is executed.

Source

Examples

Here is an example of how we can use lambda expressions with forEach() methods to apply operations on all elements of a collection.

public class Main {
  public static void main(String[] args) {
    Map<String, String> map = new HashMap<>();

    map.put("Reverse Giraffe", "parasite");
    map.put("Morty", "person");
    map.put("Sleepy Gary", "parasite");
    map.put("Beth", "person");
    map.put("Hamuray", "parasite");

    map.keySet().forEach(
      character -> System.out.println(character + ": I'm real!"));
    
    map.keySet().forEach(
      (character) -> System.out.println(character + ": Are you real?"));
    
    map.forEach(
      (character, nature) -> System.out.println(character + ": I'm a " + nature));
    
    map.forEach(
        (String character, String nature) -> System.out.println(character + ": I'm a " + nature));
    
    map.forEach(
        (character, nature) -> {
          if (nature.equals("person")) {
            System.out.println(character + ": Kill the parasites!");
          }
        });
  }
}

Here is another example of the use of lambda expressions. This time we are calculating the sum and the product of all numbers in an array.

public class IntReturn {
  public static void main(String[] args) {
    int[] values = {1, 2, 3, 4};

    int sum = reduce(values, 0, (x, y) -> x + y);
    System.out.println("Sum: " + sum);

    int product = reduce(values, 1, (x, y) -> x * y);
    System.out.println("Product: " + product);

    int sumOfSquares =
        reduce(
            values,
            0,
            (x, y) -> {
              int ySquared = (int) Math.pow(y, 2);
              return x + ySquared;
            });

    System.out.println("Sum of squares: " + sumOfSquares);
  }

  static int reduce(int[] array, int initial, BinaryOperator<Integer> operator) {
    for (int value : array) {
      initial = operator.apply(initial, value);
    }

    return initial;
  }
}