Exploring Lambdas in Java
Tags: java, lambdas, functional, programming
Published: 2022-06-05 10:33:47

This will be a quick intro to Lambdas in Java. In order to understand this tutorial, you should be familiar with the basics of writing code in Java.  If you want to follow along and try some of the code, you may use your favorite IDE; I personally use IntelliJ.

## What are lambda expressions?
The simplest way to think about a lambda expression is that it is an anonymous or unnamed method that doesn’t necessarily belong to any class.
Lambdas were introduced in Java 8 and provide us with ways to use functional programming to write more precise and powerful code in Java.

Before going any further with lambdas, we need to learn about functional interfaces. This is because lambda expressions are implementations of functional interfaces.
A **functional interface** is an interface with one and only one abstract method.

```java
@FunctionalInterface
public interface CanSwim {
    void swim();
}
```

Note the `@FunctionalInterface` annotation added to the interface. This is not required for the definition of the functional interface, but it guarantees that no other abstract methods are added to the interface.

There are many existing functional interfaces that you can explore in the [java.util.function](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/function/package-summary.html) package. They cover most of the use cases for using functional interfaces and as such, you may not have to create many of these yourself.

Now, back to lambdas. The way they relate to functional interfaces is that they are an implementation of that single abstract method of the functional interface. Here’s how that looks like based on our previous example.

```java
CanSwim fish = () -> System.out.println("I'm a fish and I'm swimming!");
fish.swim(); // Prints "I'm a fish and I'm swimming!"
```

## How do you create and use lambda expressions?
The general structure of a lambda expression is as follows.

```java
(parameter list) -> {lambda body}
```

Lambda expressions are supposed to be concise in nature. With that in mind, here are a few considerations regarding the structure above:

- Parameter list: This list can have 0, 1 or more parameters. The parentheses are mandatory except when there is a single parameter and if the type of the variable can be inferred from the context.
- The arrow: The arrow is called the arrow operator or lambda operator and is always required
- The lambda body: The curly braces around the lambda body are optional if the operation can be evaluated in a single expression. For more complex operation (declaring variables, using loops, using if statements, etc), the curly braces are required. The keyword `return` is only required in the lambda body if curly braces are used and a return value is expected.

Here are a few examples using some of the interfaces in the [java.util.function](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/function/package-summary.html) package:

```java
// Takes a single integer and has a void return type
IntConsumer printInteger = x -> System.out.println(x);
printInteger.accept(4); // Prints "4"

// Takes 2 integers and returns a string
BiFunction<Integer, Integer, String> joinNumbers = (number1, number2) -> number1 + ", " + number2;
System.out.println(joinNumbers.apply(3, 4));; // Prints "3, 4"

// Takes two Strings and returns a string
BinaryOperator<String> concatenateWords = (String word1, String word2) -> word1 + " " + word2 + "!";
System.out.println(concatenateWords.apply("Hello", "World")); // Prints "Hello World!"

// Takes an integer and returns a string
Function<Integer, String> getFizzBuzzText = number -> {
    if (((number % 5) == 0) && ((number % 7) == 0))
        return "fizzbuzz";
    else if ((number % 5) == 0)
        return "fizz";
    else if ((number % 7) == 0)
        return "buzz";
    else
        return "" + number;
};
System.out.println(getFizzBuzzText.apply(35));  // Prints "fizzbuzz"
```


## Why should we care about lambda expressions?
The power of lambda expressions resides in the fact that they allow functions to be passed around the same way you would for method parameters. As such, it is a great enabler for functional style programming, where functions or code can also be treated as “data”.

Lambdas become even more powerful when coupled with [Java Streams](https://dev.to/salmanetamo/exploring-java-streams-2baf) introduced in Java 8 allowing us to perform complex operations on collections.



This was a brief overview of Lambdas in Java. We discussed how they are implementations of functional interfaces and how they could be used. Most Lambda expressions you will write will probably implementations of the built-in functional interfaces so I recommend familiarizing yourself with those.