Java Lambda Expressions: What are they and how do they work?

Many Java developers have already encountered lambda expressions. This functionality was added in the 2014 version of Java 8, so it is no longer a new feature. It is widely used by developers and has many benefits. However, if you’re having trouble with lambda expressions or don’t know what they represent, you’ve come to the right place.

Lambda expression meaning

The lambda expression is a new feature added in Java 8. It is a short block of code similar to a method, but unlike a method, it does not need the method name and can be implemented directly in the body of the method.

Lambda has several advantages:

  • it clarifies the code and provides better readability – instead of several lines of code, you only need to write a few lines,
  • it allows you to use functional programming – that is, to use a function as an input parameter of another function,
  • it improves code parallelization – in other words, more efficient code execution on multicore processes.

Lambda expression syntax

Each lambda expression must have the correct syntax. Only then will it have the desired effect. Lambda must contain:

  • list of arguments,
  • the arrow sign,
  • the body of the expression.

In practice, it may look like this:

(argument list) -> expression body

(argument list) -> {expression1; expression2, …}

The argument list can also be empty, for example:

() -> { System.out.println(„Ahoj“); }

The body of the expression must only contain compound parentheses if it contains more than one line of code. In the above example, we can omit them:

() -> System.out.println(„Ahoj“);

The argument types may or may not be defined, which means that the two expressions are equivalent:

(x) -> System.out.println(x);

(Int x) -> System.out.println(x);

Lambda can also return values without using the return word. The compiler can infer this itself:

(x, y) -> x + y

Java lambda expressions example

To give you a better idea, here are three examples of how a lambda expression can be used.

Example No. 1: Lambda expression in forEach

Lambda expressions are often used as function parameters.

package com.test;

import java.util.ArrayList;

public class LambdaExample1 {

	public static void main(String[] args) {
		ArrayList<Integer> numbers = new ArrayList<Integer>();
		numbers.add(1);
		numbers.add(2);
		numbers.add(3);
		// Vytlaci na konzolu 1 2 3 pod sebou. 
		numbers.forEach(x -> System.out.println(x));
	}
}

The lambda expression can be saved in a variable. However, this only applies if the variable interfaces with a single method. In such cases, the lambda expression must have the same number of parameters and return type as the method.

Java has many user interfaces. One example is the consumer interface used with lists:

java.util.function.Consumer<Integer> function = x -> System.out.println(x);
numbers.forEach(function);

Example No. 2: Defining a functional interface for a lambda expression

The second example shows how to create a functional interface for basic mathematical operations. You can insert expressions for addition, subtraction, multiplication, division and the operate method. Their job is to take two numbers and the associated lambda expression calculates the result, which looks like this:

4 + 2 = 6 
4 - 2 = 2
4 * 2 = 8
4 / 2 = 2

Thanks to the operate method, the associated lambda expression calculates the result quickly and easily.

You can use lambda expressions in the functional interface for basic mathematical operations.

package com.test;

import java.lang. ArithmeticException;

public class LambdaExample2 {
    // Deklarovanie interfejsu pre lamda vyraz
    interface MathOperation {
        int operation(int x, int y);
    }
    // Deklarovanie metody pre matematicku operaciu
    private int operate (int x, int y, MathOperation mathOperation) {
        return mathOperation.operation (x, y);
    }
    // Vypis celej operacie do konzoly.
    public static void printResult(int x, char c, int y, int z) {
        System.out.printf("%d %s %d = %d\n", x, c, y, z);
    }
    public static void main(String[] args) {
        // Bez deklaracie typu
        MathOperation addition = (x, y) -> x + y;
        // S deklaraciou typu (int)
        MathOperation substraction = (int x, int y) -> x - y;
        // S klucovym slovom return (musi byt v krutenych zatvorkach)
        MathOperation multiplication = (x, y) -> { return (x * y); };
        // Viacriadkovy lambda vyraz
        MathOperation division = (x, y) -> {
            if(y != 0)
                return (x / y);
            else
                throw new ArithmeticException("You shouldn't divide a number by zero!");
        };

        LambdaExample2 test = new LambdaExample2();
        int a = 4; int b = 2;
        // Scitanie dvoch cisiel
        printResult(a, '+', b, test.operate (a, b, addition));
        // Odcitanie dvoch cisiel
        printResult(a, '-', b, test.operate (a, b, substraction));
        // Vynasobenie dvoch cisiel
        printResult(a, '*', b, test.operate (a, b, multiplication));
        // Vydelenie dvoch cisiel
        printResult(a, '/', b, test.operate (a, b, division));
    }
}

Example No. 3: Sorting, filtering and iterating collections using lambda expressions

The advantage of lambda expressions is that they reduce the need to write custom helper methods. At the same time, they also shorten and clarify the code, making the whole job easier. The power of lambdas is particularly evident when combined with other Java functionality, such as collections.

The following example shows how lambda expressions can be used to easily sort, filter and iterate objects in a collection:

package com.test;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

class Product {
    String name;
    double price;

    public Product(String name, double price) {
        this.name = name;
        this.price = price;
    }
}

public class LambdaExample3 {

    public static Product createProduct(String name, double price) {
        return new Product(name, price);
    }

    public static void main(String[] args) {
        List<Product> products = new ArrayList();
        products.add(createProduct("Chlieb", 1.0));
        products.add(createProduct("Mlieko", 0.5));
        products.add(createProduct("Keksy", 0.8));
        products.add(createProduct("Smotana", 0.4));
        products.add(createProduct ("Cokolada", 0.7));

        // Sortovanie nazvov produktov podla abecedy cez lambdu
        products.sort((p1, p2) -> p1.name.compareTo(p2.name));

        // Vyfiltrovanie produktov s cenou (0.5. 1.0)
        Stream<Product> filteredProducts = products.stream().filter(p -> p.price > 0.5 && p.price < 1.0);

        // Iterovanie v kolekcii
        filteredProducts.forEach(product -> System.out.println(product.name + ": " + product.price));
    }
}

The output looks like this:

Cokolada: 0.7
Keksy: 0.8

Lambda expressions make your work easier and faster

Lambda expressions are a great feature of the Java programming language. Using them can make your work easier and faster. They also make code cleaner and open up new possibilities. Lambda is part of Java since Java 8. So if you’re running an older version, it’s worth thinking about upgrading.

We have prepared files with the above Java Lambda examples that you can run directly in Java. Download the code here.

About the author

Jozef Wagner

Java Developer Senior

Viac ako 10 rokov programujem v Jave, momentálne pracujem v msg life Slovakia ako Java programátor senior a pomáham zákazníkom implementovať ich požiadavky do poistného softvéru Life Factory. Vo voľnom čase si rád oddýchnem v lese, prípadne si zahrám nejakú dobrú počítačovú hru.

Let us know about you