Java 8 Lambda Expression Part 1
Topics
- What is and Why Lambda Expression (or simply Lambda)?
- Lambda implementation in Java
- What is Functional interface?
- Lambda expression syntax in Java 8
What is and Why Lambda Expression?
- A formal system for “expressing computational behavior” (or “parameterizing behavior”)
- Through functions (function objects)
- Function objects are first-class citizens
- Function object can be assigned to a variable
- Function object can be passed to a method as an argument
- Function object can be returned as a return value
- Many modern programming languages support Lambda expression
- JavaScript, List, Scheme
- Ruby, Scala, Clojure
- Java 8 now supports Lambda expression
- Biggest language change since Generics of Java SE 5
Why Lambda?
- Let you declare what to do, not how to do it
- Cleaner, more concise, more expressive code
- High productivity, flexible, “fluent” style programming is possible
- Promotes immutability
- Less concurrency issues
- Enables parallel programming & lazy evaluation
- Higher performance
- Forms the basis of functional programming paradigm
- When functional programming is used, many set of problems are easier to solve, and results in cleaner code
- Richer collection APIs possible
- Stream API
- New methods in Iterable<T>, List<T>, and Map<K,V>
Java 8 Implementationof Lambda Expressionof Lambda Expression
Lambda: Concept vs. Implementation
- Lambda expression is a concept
- Different programming languages have different implementations of Lambda expression
- You, as a Java developer, need to learn both
- General concept of Lambda expression and
- How Java 8 implements Lambda expression
Java 8 Implementation of Lambda
- In Java, a Lambda expression is implemented essentially as an anonymous function
- A Lambda expression is considered as a instance of a functional interface (an interface with a single abstract method)
- The type of Lambda expression is indeed that functional interface
- There is no native “function” type (unlike in other languages), however, in Java 8 Lambda implementation
- This is a deliberate decision by Java 8 Lambda designers
Usage Areas of Lambda in Java Programs
- Replacement of anonymous inner class
- Event handling
- Iteration over list
- Parallel processing of collection elements at the API level
- Functional programming
- Streams
What is a Functional Interface (FI)?
- A regular Java interface with a single (abstract) method
- It is common in Java programs
- Sometimes called Single Abstract Method (SAM)
- Just like any other Java interface, it can be used as a reference type (type of a variable or type of an argument)
- MyFunctionalInterface x = (x, y) -> x+y;
- Even though it is a Java interface, it represents a function
- The arguments and the body of the method represents a function
- (arguments) -> {code block}
FI is simply an Interface with a single method
In fact, previous versions of Java (Java 7 and earlier versions) have several functional interfaces already
// Runnable interface
public interface Runnable {
public abstract void run();
}
// ActionListener interface
public interface ActionListener extends EventListener {
public void actionPerformed(ActionEvent e);
}// Comparator interface
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object o);// This is not considered as an abstract method
}
Backward Compatibility
- Any interface with a single method is considered as a functional interface by Java 8
- Java 8 Lambda works with old libraries that use functional interfaces without any need to recompile or modification of them
@FunctionalInterface Annotation
When used, Java 8 compiler produces an error if the interface has more than one method - helps developers at compile time (just like @Override annotation helps developers find at compile time incorrect method name )
@FunctionalInterface
public interface MyInterface {
public String myMethod();
}
// Generates Invalid @FunctionalInterface compile error
@FunctionalInterface
public interface MyInterface {
public String myMethod();
public String myMethod2();
}
Where to use Lambda Expression in Java app?
- Concept
- You use Lambda expression wherever a functional behavior is required
- Java app
- You can use Lambda expression in any place where the functional interface type is expected
- Examples
- You can assign a lambda expression to a variable whose type is a functional interface
- You can pass a lambda expression to a method as an argument whose type is a functional interface
Example #1: Variable is functional interface type
- Let's say we have a functional interface
@FunctionalInterface
public interface Calculator {
int calculate(int x, int y);
}
- A variable whose type is a functional interface can be assigned with a lambda expression
Calculator multiply = (x,y) -> x*y;
Calculator divide = (x,y) ->x/y;
int product = multiply.calculate(50,10);
int quotient = divide.calculate(50,10);
Example #2: An argument is functional interface
Let's say we have a functional interface (same as in prev. slide)
@FunctionalInterface
public interface Calculator {
int calculate(int x, int y);
}
Types of arguments are functional interface
public static void myMethod(Calculator m, Calculator d){
int product = m.calculate(60, 10);
int quotient = d.calculate(60, 10);
System.out.println("product = " + product + " quotient = " + quotient);
}
Pass lambda expressions as arguments of a method
myMethod((x,y)->x+y, (x,y)->x/y);
Lab: Exercise 1: Functional Interface 1611_javase8_lambda_syntax.zip
Anonymous Inner Class Replaced by Lambda
- Given that typical usage of anonymous inner class is an example of an argument whose type is a functional interface, you can now replace it with a Lambda expression
- In Java programs (of pre-Java 8 versions), anonymous inner class has been used as a kludge solution for passing a functional behavior (before Lambda is available in Java 8)
- The current code what uses Anonymous Inner class can be simplified through the usage of Lambda
- Just take the arguments and code block with following Lambda syntax removing everything else
- (arguments) -> {code block}
Example #1: Runnable
Anonymous Runnable replaced by Lambda
// Anonymous Runnable
Runnable r1 = new Runnable() {
@Override
public void run() {
// Just take arguments and body to make lambda expression
System.out.println("Hello world one!");
}
};
r1.run();
// Lambda Runnable
Runnable r2 = () -> System.out.println("Hello world two!");
r2.run();
Example #2: Action Listener
Anonymous ActionListener replaced by Lambda
// Anonymous ActionListener
testButton1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
// just take arguments and body to make lambda expression
System.out.println("Click Detected by Anonymous Listener");
}
});
// Lambda ActionListener
testButton2.addActionListener(event -> System.out.println("Click Detected by Lambda
Listener"));
Example #3: Comparator
Anonymous Comparator replaced by Lambda
// Anonymous Comparator
Collections.sort(personList, new Comparator<Person>(){
public int compare(Person p1, Person p2){
//just take arguments and body to make lambda expresison
return p1.getSurName().compareTo(p2.getSurName());
}
});
// Lambda Comparator
Collections.sort(personList, (Person p1, Person p2) →
p1.getSurName().compareTo(p2.getSurName()));
Lab: Exercise 2: Rewriting Anonymous Inner Class with Lambda Expression 1611_javase8_lambda_syntax.zip
Lambda Expression Syntax in Java
Lambda Expression Syntax
- General syntax
- (argument list) -> { code block}
- Syntax can be simplified in the following ways
- #1: Type inferencing for the arguments
- #2: Omitting parentheses for a single argument
- #3: When a body has only a single expression - (1) no need to use return, (2) no need to use semi-colon, (3) no need to use curly braces {..}
#1: Type inferencing for the arguments
- Types in argument list can be omitted
- Java compiler already knows the types of the arguments from the single method signature of the functional interface of the lambda expression
// Instead of this
(String myArg1, Integer myArg2) → {... }
// You can do this because types of the arguments can be inferred by the compiler
(myArg1, myArg2) → {… }
#2: Single argument with no ( )
If there is a single argument, parentheses ( ) are optional
// Instead of this
(myArg1) → {... }
// You can do this because there is a single argument
myArg1 → {… }
#3: When body has only a single expression
- When the body (code block) has only a single expression, the value of the expression automatically becomes a return value
- No need to specify return statement
- No need to use semi-colon at the end
- No need to enclose the expression with { }
- If the body has multi-line code, then no simplification is allowed
// Instead of this
(myArg1, myArg2) → { return (someExpression); }
// You can do this because the body has only a single expression
(myArg1, myArg2) → someExpression
Simplification Examples of Lambda Expression
(int x, int y) -> { return x+y;}
(x,y) -> { return x+y;}
(x,y) -> x+y
x -> x*2
() -> System.out.println(“Hello, world!”)
//You have to use curly braces{}and user return statement because there are multiple statements
x -> { System.out.println(x);
System.out.println(x*2);
return x*2; }
Lab: Exercise 3: Lambda Expression Syntax Simplification 1611_javase8_lambda_syntax.zip
Download Course Content