Java Lambda Expressions Basics
Learn about Java Lambda essentials, including basics and examples.
Join the DZone community and get the full member experience.
Join For FreeWhat 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
- Given a number n returns a boolean indicating if it is odd.
- Given a character c returns a boolean indicating if it is equal to ‘y’.
- Given two numbers x and y returns another number with their summation.
- Given two integers a and b returns another integer with the sum of their squares.
- Given no parameters returns the integer 42.
- Given no parameters returns the double 3.14.
- Given a string s prints the string to the main output and returns void.
- 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
- Getting Rid of Boilerplate Code with Lambda Expressions
- Java Lambda Expressions vs Method References
- Java Infinite Streams
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.
- Project Lambda Home Page
- JDK 8 Early Access
- Lambda FAQ (by Maurice Naftalin)
- State of Lambda 4 (Dic. 2011)
Published at DZone with permission of Edwin Dalorzo. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments