Lambda functions in Java in 5 minutes

You might already be familiar with Lambda expression if you are coming from Javascript or other non-natively typed languages. In those languages, you can just create a lambda expression (argument and return body) and treat it like a variable (you can pass it to methods and function arguments). Example in Js ES6:

// create ES6 anonymous function and use it
printer = (t) => console.log(t);
printer(“Hello”);

Java introduced lambda expression too from version 8, with a similar expression syntax, but the difference is that every variable in Java has a type (either native or a class/interface), and everything has to stay in a class (no functions, only methods). So, as you can guess, the type of a lambda expression is any interface with a single method. Here is an example with a generic type and a method arbitrarily called accept():

interface MyInterface<T> {
void accept(T t);
}

This is the type corresponding to a lambda function that takes a variable, and does something with it without returning anything (void). Let’s implement first the interface the non-lambda way to print the value to the console:

public class LambdaSample {

public static void main(String[] args) {
MyInterface<String> printer1 = new MyInterface<String>() {
public void accept(String t) {
System.out.println(t);
}
}
;

printer1.accept("hello");
}
}

We basically created an implementation and launched its method. The equivalent (but not the same in terms of bytecode) with a Java lambda expression is the following:

MyInterface<String> printer2 = t -> System.out.println(t);
printer2.accept("hello");

In both cases, we created an implementation, and then called its method passing the argument. The method just did what was implemented for (print the value).

Note1: the MyInterface<String> is the type of the expression, and could be used in a method e.g.

private static void methodAcceptingInterface(MyInterface mi) {
mi.accept("hello from method");
}

Note 2: lambda expression can specify argument type and also require curly braces and return type when there is more than one instruction. There is also as shorter syntax that allow the This example it can also be written as

Consumer<String> printer = System.out::println

Refer to the documentation if needed.

As you might have notice, the interface we wrote can be reused for any other lambda expression that accepts a type and returns void. Java already includes some interfaces (called functional interfaces) with different generic input and output (see the list here). In this specific case, an interface with method accept() that returns nothings is called Consumer, and can be used instead of our interface. The whole code above can therefore be written as:

import java.util.function.Consumer;

public class LambdaSample {

public static void main(String[] args) {
Consumer<String> printer = (String i) -> System.out.println(i);
printer.accept("hello");
}
}

The method Collections:removeIf() accepts a functional interface Predicate<T> (the functional interface accepting a type and returning a boolean). As you can imagine this method removes the object that returns true when passed on our implementation (lamba expression) of the interface. Here is an example that creates a list of numbers 1 to 5 and removes the even ones:

List<Integer> list = Stream.of(1,2,3,4,5)
.collect(Collectors.toList());
list.removeIf(i -> i%2 == 0);
System.out.println(list); //[1, 3, 5]

Thanks for reading and clap if useful

Software Engineer @ London

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store