Java lambda functions and comparison with other languages

Elvis Ciotti
2 min readApr 29, 2020

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”);

How to do the same in Java

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 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 in 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’ve just 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.

Note that Myterface<String> is the lambda Java type.

In case the lambda accepts only one argument, you can also use the method reference

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

Existing Java interfaces

As you might have noticed, 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 inputs and outputs (see the list here). In this specific case, an interface with method accept() that returns nothing 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");
}
}

Example passing a lambda function to a native Java method

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 (lambda 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

--

--

Elvis Ciotti

Software Contractor — Java, Spring, k8s, AWS, Javascript @ London - hire me at https://www.linkedin.com/in/elvisciotti