Skip to main content

Lambda

  • A lambda expression can be thought of as implicit code for an anonymous class, using a special kind of interface, as the mechanics to do this
  • The method reference goes even further, and is a shortcut for the lambda expression syntax, for existing methods

The Lambda Expressionโ€‹

Lambda ExpressionComparatorโ€™s Abstract Method
(o1, o2) -> o1.lastName().compareTo(o2.lastName())int compare(T o1, T o2)
  • The lambda expression parameters are determined by the associated interface's method, the functional method
  • A lambda expression consists of a formal parameter list, usually but not always declared in parentheses; the arrow token; and either an expression or a code block after the arrow token
  • The expression should return a value, if the associated interface's method returns a value

Anonymous class and the lambda expressionโ€‹

Anonymous Classโ€‹

new Comparator<Person>() {

@Override
public int compare(Person o1, Person o2) {
return o1.lastName().compareTo(o2.lastName());
}
}

Lambda Expressionโ€‹

(o1,o2)->o1.lastName().compareTo(o2.lastName());
  • Lambda expression has no reference to an enclosing method, the method is inferred by Java
  • Java requires types which support lambda expressions, to be something called a functional interface
  • A functional interface is an interface that has one, and only one, abstract method
  • A functional interface is the target type for a lambda expression

Lambda expression variationsโ€‹

For a single parameterโ€‹
Lambda ExpressionDescription
element -> System.out.println(element);A single parameter without a type can omit the parentheses
(element) -> System.out.println(element);Parentheses are optional
(String element) -> System.out.println(element);Parentheses required if a reference type is specified
(var element) -> System.out.println(element);A reference type can be var
The lambda bodyโ€‹
Single expressionโ€‹
element ->System.out.println(element);
Code blockโ€‹
element -> {
char first = element.chartAt(0);
System.out.println(element + " means " + first);
};
With multiple parametersโ€‹
Lambda ExpressionDescription
(a, b) -> a + b;Parentheses are always required. Explicit types are not
(Integer a, Integer b) -> a + b;If you use an explicit type for one parameter, you must use explicit types for all the parameters
(var a, var b) -> a + b;If you use var for one parameter, you must use var for all parameters
The lambda bodyโ€‹
Single expressionโ€‹
(a,b) -> a +b;
Code blockโ€‹
(a,b) -> {
var c = a + b;
return c;
};

java.util.functionโ€‹

  • Java provides a library of functional interfaces in the java.util.function package

Basic categories of Functional Interfacesโ€‹

Interface CategoryBasic Method SignaturePurpose
Consumervoid accept(T t)execute code without returning data
FunctionR apply(T t)return a result of an operation or function
Predicateboolean test(T t)test if a condition is true or false
SupplierT get()return an instance of something

The Consumer interfaceโ€‹

The two most common:

Interface NameMethod Signature
Consumervoid accept(T t)
BiConsumervoid accept(T t, U u)

Example:

s -> System.out.println(s)

The Predicate Interfaceโ€‹

The two most common:

Interface NameMethod Signature
Predicateboolean test(T t)
BiPredicateboolean test(T t, U u)

Example:

s -> s.equalsIgnoreCase("Hello")

The Function Interfaceโ€‹

The four most common:

Interface NameMethod Signature
Function<T, R>R apply(T t)
BiFunction<T, U, R>R apply(T t, U u)
UnaryOperator<T>T apply(T t)
BinaryOperator<T>T apply (T t1, T t2)

Example:

Function<String, String[]> function = s -> s.split(",")

The Supplier Interfaceโ€‹

Takes no argument, but lambda expressions can use final or effectively final variables in their expressions

Example:

() -> random.nextInt(1,100)

Valid Lambda Declarationsโ€‹

Arguments in Functional MethodValid lambda syntax
None() -> statement
Ones -> statement
(s) -> statement
(var s) -> statement
(String s) -> statement
Two
1. When using var, all arguments must use var
2. When specifying explicit types, all arguments must specify explicit types
(s, t) -> statement
(var s, var t) -> statement
(String s, List t) -> statement

Method Referenceโ€‹

  • Methods which can be used, are based on the context of the lambda expression
  • This means the method reference, is again dependent on the targeted interface's method
  • We can reference a static method on a class
  • We can reference an instance method from either an instance external to the expression, or an instance passed as one of the arguments
  • Or you can reference a constructor, by using new as the method
Lambda ExpressionMethod Reference
s -> System.out.println(s)System.out::println

Deferred Method Invocationโ€‹

  • When you create variables that are lambda expressions or method references, it's important to remember that the code isn't invoked at that point
  • The statement or code block gets invoked at the point in the code that the targeted functional method is called

For static methodsโ€‹

Integer::sum

For a Bounded Receiverโ€‹

An instance derived from the enclosing code, used in the lambda expression, on which the method will be invoked

System.out::println

For an Unbounded Receiverโ€‹

The first argument becomes the instance used, on which the method gets invoked

String::concat
TypeSyntaxMethod Reference ExampleCorresponding Lambda Expression
static methodClassName::staticMethodName(p1, p2, ... pn)Integer::sum(p1, p2) -> p1 + p2
instance method of a particular (Bounded) objectContainingObject::instanceMethodName(p1, p2, ... pn)System.out::printlnp1 -> System.out.println(p1)
instance method of an arbitrary (Unbounded) object (as determined by p1)ContainingType[=p1]::instanceMethodName(p2, ... pn)String::concat(p1, p2) -> p1.concat(p2)
constructorClassName::newPlayer::new() -> new Player()

Convenience Methodsโ€‹

Category of InterfaceConvenience method exampleNotes
Functionfunction1.andThen(function2)Not implemented on IntFunction, DoubleFunction, LongFunction
Functionfunction2.compose(function1)Only implemented on Function & UnaryOperator
Consumerconsumer1.andThen(consumer2)
Predicatepredicate1.and(predicate2)
Predicatepredicate1.or(predicate2)
Predicatepredicate1.negate()

Comparator's additional helper methodsโ€‹

Type of MethodMethod Signature
staticComparator comparing(Function keyExtractor)
staticComparator naturalOrder()
staticComparator reverseOrder()
defaultComparator thenComparing(Comparator other)
defaultComparator thenComparing(Function keyExtractor)
defaultComparator reversed()