Edwin is a software developer, programming languages enthusiast and a novice photographer. Edwin is a DZone MVB and is not an employee of DZone and has posted 12 posts at DZone. You can read more from them at their website. View Full User Profile

Java Lambda Expressions Basics

04.13.2013
| 28264 views |
  • submit to reddit

What is a Lambda Expression?

A lambda expression represents an anonymous function. It comprises of a set of parameters, a lambda operator (->) and a function body.

The following are examples of Java lambda expressions:

n -> n % 2 != 0;
(char c) -> c == 'y';
(x, y) -> x + y;
(int a, int b) -> a * a + b * b;
() -> 42
() -> { return 3.14 };
(String s) -> { System.out.println(s); };
() -> { System.out.println("Hello World!"); };

Interpretation of Examples

  1. Given a number n returns a boolean indicating if it is odd.
  2. Given a character c returns a boolean indicating if it is equal to ‘y’.
  3. Given two numbers x and y returns another number with their summation.
  4. Given two integers a and b returns another integer with the sum of their squares.
  5. Given no parameters returns the integer 42.
  6. Given no parameters returns the double 3.14.
  7. Given a string s prints the string to the main output and returns void.
  8. Give no parameters prints Hello World! to the main output and returns void.

The Parameters

  • A lambda expression can receive zero, one or more parameters.
  • The type of the parameters can be explicitly declared or it can be inferred from the context.
  • Parameters are enclosed in parentheses and separated by commas.
  • Empty parentheses are used to represent an empty set of parameters.
  • When there is a single parameter, if its type is inferred, it is not mandatory to use parentheses.

The Body

  • The body of the lambda expression can contain zero, one or more statements.
  • When there is a single statement curly brackets are not mandatory and the return type of the anonymous function is the same as that of the body expression.
  • When there is more than one statement then these must be enclosed in curly brackets (a code block) and the return type of the anonymous function is the same as the type of the value returned within the code block, or void if nothing is returned.

What is a Java Functional Interface

In Java, a functional interface is basically an interface with a single abstract method. This kind of interfaces are also known as SAM (Single Abstract Method) types.

Before Java 8 there were already several interfaces compatible with this idea:

public interface Comparator<T> {
    int compare(T o1, T o2);
}
 
public interface Callable<V> {
    V call() throws Exception;
}
 
public interface ActionListener extends EventListener {
    public void actionPerformed(ActionEvent e);
}
 
public interface Runnable {
    public void run();
}

Java 8 Examples

Many new functional interfaces are being defined in the Java 8, among the most popular, those found in the new java.util.function package. The following are some examples of new functional interfaces in Java:

public interface Predicate<T> {
    boolean test(T t);
}
 
public interface Function<T,R> {
    R apply(T t);
}
 
public interface BinaryOperator<T> {
    T apply(T left, T right);
}
 
public interface Consumer<T> {
    void accept(T t);
}
 
public interface Supplier<T> {
    T get();
}

Starting with Java 8 these functional interfaces can be implemented by means of lambda expressions and method references.

What is the Type of Lambda Expression?

In languages that support first class functions, the type of the lambda expression would be a function; but in Java, the lambda expressions are represented as objects, and so they must be bound to a particular object type known as a functional interface. This is called the target type.

Since a functional interface can only have a single abstract method, the types of the lambda expression parameters must correspond to the parameters in that method, and the type of the lambda body must correspond to the return type of this method. Additionally, any exceptions thrown in the lambda body must be allowed by the throws clause of this method in the functional interface.

The following are examples of lambda expressions bound to a target type:

Predicate<Integer> isOdd = n -> n % 2 != 0;
BinaryOperator<Integer> sum = (x, y) -> x + y;
Callable<Integer> callMe = () -> 42;
Block<String> printer -> (String s) -> { System.out.println(s); };
Runnable runner = () -> { System.out.println("Hello World!"); };

See the Java documentation for the new java.util.function package to get more details on these functional interfaces and their corresponding abstract methods.

Notice that the type of the lambda expression is determined by the compiler from the context based on the target type. This implies that two apparently equal lambda expressions may have different types simply because they are bound to a different target type as demonstrated in the following code.

Callable<String> callMe = () -> "Hello";
PrivilegedAction<String> action = () -> "Hello"

Example

Supposing we had a functional interface named Predicate declared as follows:

public interface Predicate<T> {
    boolean test(T input);
}

Now imagine that we had a method capable of filtering the contents of a Collection based on a provided Predicate as follows:

public static <T> Collection<T> filter(Predicate<T> predicate,
                                       Collection<T> items) {
    Collection<T> result = new ArrayList<T>();
    for(T item: items) {
        if(predicate.test(item)) {
            result.add(item);
        }
    }
    return result;
}

Now, since the predicate parameter is of a functional interface type we could bind a lambda expression to the predicate parameter as follows:

Collection<Integer> myInts = asList(0,1,2,3,4,5,6,7,8,9);
Collection<Integer> onlyOdds = filter(n -> n % 2 != 0, myInts);

As you can see in the highlighted line 2, the type of the lambda expression is the functional interface Predicate. Its parameter n corresponds to the required parameter in the test method, and the type of the lambda expression body corresponds to the return type of the test method, in this case: boolean.

Related Posts in this Blog

Further Reading

For those of you who found the talk interesting and would like to delve much more, you can use the following reference material.





 

Published at DZone with permission of Edwin Dalorzo, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)