633 lines
9.6 KiB
Plaintext
633 lines
9.6 KiB
Plaintext
|
Application
|
|||
|
Programming
|
|||
|
Hend Alkittawi
|
|||
|
|
|||
|
Lambda Expressions
|
|||
|
Introduction to Lambda Expressions
|
|||
|
in Java
|
|||
|
|
|||
|
INTRODUCTION
|
|||
|
-
|
|||
|
|
|||
|
To understand Java’s implementation of lambda expressions we
|
|||
|
need to understand what Functional Interfaces and a Lambda
|
|||
|
Expressions are!
|
|||
|
|
|||
|
-
|
|||
|
|
|||
|
A Functional Interface is an interface that contains one and
|
|||
|
only one abstract method
|
|||
|
|
|||
|
-
|
|||
|
|
|||
|
A Lambda Expression is an anonymous (unnamed) method, used to
|
|||
|
implement a method defined by a functional interface
|
|||
|
|
|||
|
-
|
|||
|
|
|||
|
A functional interface defines a target type of a lambda
|
|||
|
expression!
|
|||
|
|
|||
|
LAMBDA EXPRESSIONS FUNDAMENTALS
|
|||
|
-
|
|||
|
|
|||
|
Lambda expressions use the lambda operator (->)
|
|||
|
-
|
|||
|
|
|||
|
left-side: specifies any parameters requires by the lambda expression
|
|||
|
|
|||
|
-
|
|||
|
|
|||
|
right-side: the lambda body which specifies the actions of the lambda
|
|||
|
expression
|
|||
|
(parameters) -> (body)
|
|||
|
|
|||
|
-
|
|||
|
|
|||
|
Lambda body can be
|
|||
|
-
|
|||
|
|
|||
|
-
|
|||
|
|
|||
|
single expression
|
|||
|
-
|
|||
|
|
|||
|
() -> (123.45)
|
|||
|
|
|||
|
-
|
|||
|
|
|||
|
() -> (Math.random() * 100)
|
|||
|
|
|||
|
-
|
|||
|
|
|||
|
(n) -> ( (n%2) == 0 )
|
|||
|
|
|||
|
block of code
|
|||
|
-
|
|||
|
|
|||
|
(n) -> {
|
|||
|
|
|||
|
for(int i = 0; i < n; i++)
|
|||
|
System.out.println(i); }
|
|||
|
|
|||
|
LAMBDA EXPRESSIONS FUNDAMENTALS
|
|||
|
-
|
|||
|
|
|||
|
A lambda expression is not executed on its own; it forms the
|
|||
|
implementation of the abstract method defined by the functional
|
|||
|
interface that specifies its target type!
|
|||
|
|
|||
|
-
|
|||
|
|
|||
|
The lambda expression can be specified only in a context in
|
|||
|
which a target type is specified.
|
|||
|
-
|
|||
|
|
|||
|
one of these contexts is created when a lambda expression is
|
|||
|
assigned to a functional interface reference.
|
|||
|
|
|||
|
FunctionalInterface var = (parameters) -> (body);
|
|||
|
|
|||
|
LAMBDA EXPRESSIONS SINGLE EXPRESSION
|
|||
|
-
|
|||
|
|
|||
|
An instance of a class is
|
|||
|
automatically created that implements
|
|||
|
the functional interface, with the
|
|||
|
lambda expression defining the
|
|||
|
behavior of the abstract method
|
|||
|
declared by the functional interface.
|
|||
|
|
|||
|
-
|
|||
|
|
|||
|
public interface MyNumber {
|
|||
|
public double getValue();
|
|||
|
}
|
|||
|
|
|||
|
public class MyFirstNumber implements MyNumber{
|
|||
|
@Override
|
|||
|
public double getValue() {
|
|||
|
return 100;}
|
|||
|
}
|
|||
|
|
|||
|
public class MySecondNumber implements MyNumber{
|
|||
|
@Override
|
|||
|
public double getValue() {
|
|||
|
return Math.random() * 100; }
|
|||
|
}
|
|||
|
|
|||
|
public class LambdaDemo {
|
|||
|
public static void main(String[] args) {
|
|||
|
|
|||
|
When that method is called through
|
|||
|
|
|||
|
MyFirstNumber first = new MyFirstNumber();
|
|||
|
double m = first.getValue();
|
|||
|
|
|||
|
the target, the lambda expression is
|
|||
|
|
|||
|
MySecondNumber second = new MySecondNumber();
|
|||
|
double n = second.getValue();
|
|||
|
|
|||
|
executed
|
|||
|
-
|
|||
|
|
|||
|
The lambda expression gives us a way
|
|||
|
|
|||
|
MyNumber x = () -> 100;
|
|||
|
MyNumber y = () -> Math.random() * 100;
|
|||
|
|
|||
|
to transform a code segment into an
|
|||
|
|
|||
|
System.out.println("m: " + m + " n: " + n +
|
|||
|
" x: " + x.getValue() + " y: " + y.getValue());
|
|||
|
// MyNumber z = () -> "123.5";
|
|||
|
|
|||
|
object!
|
|||
|
}
|
|||
|
|
|||
|
LAMBDA EXPRESSIONS - SINGLE EXPRESSION
|
|||
|
-
|
|||
|
|
|||
|
The type of the parameter
|
|||
|
(n) is not specified; it is
|
|||
|
|
|||
|
public interface NumericTest {
|
|||
|
public boolean test(int n);
|
|||
|
}
|
|||
|
|
|||
|
inferred from the context.
|
|||
|
-
|
|||
|
|
|||
|
-
|
|||
|
|
|||
|
The parameter type of test()
|
|||
|
|
|||
|
public class LambdaDemo {
|
|||
|
public static void main(String[] args) {
|
|||
|
|
|||
|
It is possible to explicitly
|
|||
|
|
|||
|
NumericTest isEven = (n) -> (n % 2) == 0;
|
|||
|
System.out.println(isEven.test(5));
|
|||
|
System.out.println(isEven.test(6));
|
|||
|
|
|||
|
specify the type of the
|
|||
|
|
|||
|
NumericTest isPositive = (n) -> (n > 0);
|
|||
|
|
|||
|
parameter in a lambda
|
|||
|
expression
|
|||
|
-
|
|||
|
|
|||
|
( int n ) -> ( n % 2) == 0
|
|||
|
|
|||
|
System.out.println(isPositive.test(-1));
|
|||
|
System.out.println(isPositive.test(1));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
LAMBDA EXPRESSIONS - CODE BLOCK
|
|||
|
-
|
|||
|
|
|||
|
A block lambda encloses the body within braces { }
|
|||
|
|
|||
|
-
|
|||
|
|
|||
|
The block body of a lambda is similar to a method body
|
|||
|
|
|||
|
public interface NumericFunction {
|
|||
|
public int func(int n);
|
|||
|
}
|
|||
|
|
|||
|
public class LambdaDemo {
|
|||
|
public static void main(String[] args) {
|
|||
|
NumericFunction factorial = (n) -> { int result = 1;
|
|||
|
for (int i = 1; i <= n; i++) {
|
|||
|
result = result * i;
|
|||
|
}
|
|||
|
return result;
|
|||
|
};
|
|||
|
System.out.println(factorial.func(5));
|
|||
|
|
|||
|
public interface StringFunction {
|
|||
|
public String func(String n);
|
|||
|
}
|
|||
|
|
|||
|
StringFunction reverse = (str) -> { String result = "";
|
|||
|
for (int i = str.length() - 1; i >= 0; i--) {
|
|||
|
result = result + str.charAt(i);
|
|||
|
}
|
|||
|
return result;
|
|||
|
};
|
|||
|
System.out.println(reverse.func("Lambda"));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
LAMBDA EXPRESSIONS FUNDAMENTALS
|
|||
|
-
|
|||
|
|
|||
|
The functional interface associated with a lambda
|
|||
|
expression can be generic.
|
|||
|
|
|||
|
public interface NumericFunction {
|
|||
|
public int func(int n);
|
|||
|
}
|
|||
|
|
|||
|
public class LambdaDemo {
|
|||
|
public static void main(String[] args) {
|
|||
|
SomeFunction<Integer> factorial = (n) -> { int result = 1;
|
|||
|
for (int i = 1; i <= n; i++){
|
|||
|
result = result * i;
|
|||
|
}
|
|||
|
return result;
|
|||
|
};
|
|||
|
System.out.println(factorial.func(5));
|
|||
|
|
|||
|
public interface StringFunction {
|
|||
|
public String func(String n);
|
|||
|
}
|
|||
|
|
|||
|
SomeFunction<String> reverse = (str) -> { String result = "";
|
|||
|
for (int i = str.length() - 1; i >= 0; i--){
|
|||
|
result = result + str.charAt(i);
|
|||
|
}
|
|||
|
return result;
|
|||
|
};
|
|||
|
System.out.println(reverse.func("Lambda"));
|
|||
|
|
|||
|
public interface SomeFunction<T> {
|
|||
|
public T func(T t);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
LAMBDA EXPRESSION FUNDAMENTALS
|
|||
|
-
|
|||
|
|
|||
|
A lambda expression can be
|
|||
|
passed as an argument to a
|
|||
|
method.
|
|||
|
|
|||
|
-
|
|||
|
|
|||
|
A very powerful use of lambda
|
|||
|
|
|||
|
public interface StringFunction {
|
|||
|
public String func(String n);
|
|||
|
}
|
|||
|
|
|||
|
public class LambdaDemo {
|
|||
|
|
|||
|
expressions which gives you a
|
|||
|
|
|||
|
-
|
|||
|
|
|||
|
public static void main(String[] args) {
|
|||
|
|
|||
|
way to pass executable code as
|
|||
|
|
|||
|
String inStr = "Lambdas Add Power To Java!";
|
|||
|
|
|||
|
an argument to a method
|
|||
|
|
|||
|
StringFunction capitalize = (str) -> str.toUpperCase();
|
|||
|
String outStr1 = stringOp(capitalize, inStr);
|
|||
|
|
|||
|
The type of the parameter
|
|||
|
|
|||
|
String outStr2 = stringOp( (str) -> str.toLowerCase(), inStr);
|
|||
|
System.out.println("inStr: " + inStr
|
|||
|
+ " outStr1: " + outStr1
|
|||
|
+ " outStr2: " + outStr2);
|
|||
|
|
|||
|
receiving the lambda
|
|||
|
}
|
|||
|
|
|||
|
expression must be of a
|
|||
|
|
|||
|
public static String stringOp(StringFunction sf, String s) {
|
|||
|
return sf.func(s);
|
|||
|
}
|
|||
|
|
|||
|
functional interface
|
|||
|
compatible with the lambda
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
PREDEFINED FUNCTIONAL INTERFACES
|
|||
|
-
|
|||
|
|
|||
|
The previous examples have defined their own functional
|
|||
|
interfaces.
|
|||
|
|
|||
|
-
|
|||
|
|
|||
|
In many cases, there is no need to define your own functional
|
|||
|
interface; Java’s java.util.function package provides several
|
|||
|
predefined functional interfaces!
|
|||
|
Interface
|
|||
|
|
|||
|
Method
|
|||
|
|
|||
|
Parameter(s)
|
|||
|
|
|||
|
Returns
|
|||
|
|
|||
|
Function<T,R>
|
|||
|
|
|||
|
apply
|
|||
|
|
|||
|
T
|
|||
|
|
|||
|
R
|
|||
|
|
|||
|
Predicate<T>
|
|||
|
|
|||
|
test
|
|||
|
|
|||
|
T
|
|||
|
|
|||
|
boolean
|
|||
|
|
|||
|
UnaryOperator<T>
|
|||
|
|
|||
|
apply
|
|||
|
|
|||
|
T
|
|||
|
|
|||
|
T
|
|||
|
|
|||
|
BinaryOperator<T>
|
|||
|
|
|||
|
apply
|
|||
|
|
|||
|
T, T
|
|||
|
|
|||
|
T
|
|||
|
|
|||
|
FUNCTION<T, R> INTERFACE
|
|||
|
-
|
|||
|
|
|||
|
The Function interface requires a parameter type and a return
|
|||
|
type.
|
|||
|
|
|||
|
-
|
|||
|
|
|||
|
Interface
|
|||
|
|
|||
|
Method
|
|||
|
|
|||
|
Parameter(s)
|
|||
|
|
|||
|
Returns
|
|||
|
|
|||
|
Function<T,R>
|
|||
|
|
|||
|
apply
|
|||
|
|
|||
|
T
|
|||
|
|
|||
|
R
|
|||
|
|
|||
|
public interface Function<T, R> {
|
|||
|
public R apply(T t);
|
|||
|
}
|
|||
|
|
|||
|
A usage example …
|
|||
|
Function<Integer,Double> getHalf = (x) -> (x / 2.0);
|
|||
|
double result = getHalf.apply( 5 );
|
|||
|
|
|||
|
PREDEFINED FUNCTIONAL INTERFACES - EXAMPLE
|
|||
|
public interface NumericFunction {
|
|||
|
public int func(int n);
|
|||
|
}
|
|||
|
|
|||
|
public class LambdaDemo {
|
|||
|
public static void main(String[] args) {
|
|||
|
NumericFunction factorial = (n) -> { int result = 1;
|
|||
|
for (int i = 1; i <= n; i++)
|
|||
|
result = result * i;
|
|||
|
return result;
|
|||
|
};
|
|||
|
System.out.println(factorial.func(5));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Interface
|
|||
|
|
|||
|
Method
|
|||
|
|
|||
|
Parameter(s)
|
|||
|
|
|||
|
Returns
|
|||
|
|
|||
|
Function<T,R>
|
|||
|
|
|||
|
apply
|
|||
|
|
|||
|
T
|
|||
|
|
|||
|
R
|
|||
|
|
|||
|
public interface Function<T, R> {
|
|||
|
public R apply(T t);
|
|||
|
}
|
|||
|
|
|||
|
public class LambdaDemo {
|
|||
|
public static void main(String[] args) {
|
|||
|
Function<Integer, Integer> factorial = (n) -> { int result = 1;
|
|||
|
for (int i = 1; i <= n; i++)
|
|||
|
result = result * i;
|
|||
|
return result;
|
|||
|
};
|
|||
|
System.out.println(factorial.apply(5));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
PREDICATE<T> INTERFACE
|
|||
|
-
|
|||
|
|
|||
|
The Predicate interface requires a parameter type and returns
|
|||
|
a boolean.
|
|||
|
|
|||
|
-
|
|||
|
|
|||
|
Interface
|
|||
|
|
|||
|
Method
|
|||
|
|
|||
|
Parameter(s)
|
|||
|
|
|||
|
Returns
|
|||
|
|
|||
|
Predicate<T>
|
|||
|
|
|||
|
test
|
|||
|
|
|||
|
T
|
|||
|
|
|||
|
boolean
|
|||
|
|
|||
|
public interface Predicate<T> {
|
|||
|
public boolean test(T t);
|
|||
|
}
|
|||
|
|
|||
|
A usage example …
|
|||
|
Predicate<Double> checkPassing =(grade)->(grade >= 60);
|
|||
|
boolean isPassing = checkPassing.test( 68.5 );
|
|||
|
|
|||
|
UNARY OPERATOR
|
|||
|
-
|
|||
|
|
|||
|
The UnaryOperator interface requires a parameter type and
|
|||
|
returns a value of the same type
|
|||
|
|
|||
|
-
|
|||
|
|
|||
|
Interface
|
|||
|
|
|||
|
Method
|
|||
|
|
|||
|
Parameter(s)
|
|||
|
|
|||
|
Returns
|
|||
|
|
|||
|
UnaryOperator<T>
|
|||
|
|
|||
|
apply
|
|||
|
|
|||
|
T
|
|||
|
|
|||
|
T
|
|||
|
|
|||
|
public interface UnaryOperator<T> {
|
|||
|
public T apply(T t);
|
|||
|
}
|
|||
|
|
|||
|
An usage example …
|
|||
|
UnaryOperator<Integer> uSquare = (i) -> (i*i);
|
|||
|
int result = uSquare.apply( 3 );
|
|||
|
|
|||
|
BINARY OPERATOR
|
|||
|
-
|
|||
|
|
|||
|
The BinaryOperator interface requires a parameter type and
|
|||
|
returns a value of the same type.
|
|||
|
|
|||
|
-
|
|||
|
|
|||
|
Interface
|
|||
|
|
|||
|
Method
|
|||
|
|
|||
|
Parameter(s)
|
|||
|
|
|||
|
Returns
|
|||
|
|
|||
|
BinaryOperator<T>
|
|||
|
|
|||
|
apply
|
|||
|
|
|||
|
T, T
|
|||
|
|
|||
|
T
|
|||
|
|
|||
|
public interface BinaryOperator<T> {
|
|||
|
public T apply(T t1, T t2);
|
|||
|
}
|
|||
|
|
|||
|
A usage example
|
|||
|
BinaryOperator<Integer> bMult = (a, b)-> (a * b);
|
|||
|
int result = bMult.apply( 5, 2 );
|
|||
|
|
|||
|
LAMBDA EXPRESSIONS AND ANONYMOUS INNER CLASSES
|
|||
|
-
|
|||
|
|
|||
|
Inner classes are classes defined within another class.
|
|||
|
|
|||
|
-
|
|||
|
|
|||
|
An anonymous inner class is a class without a name, for which
|
|||
|
only one object is created!
|
|||
|
public static Comparator<Book> bookComparator = new Comparator<Book>() {
|
|||
|
public int compare(Book book1, Book book2) {
|
|||
|
return book1.getTitle().compareTo(book2.getTitle());
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
-
|
|||
|
|
|||
|
A lambda expression can be utilized instead of an anonymous
|
|||
|
inner class
|
|||
|
public static Comparator<Book> bookComparator = (book1, book2) -> {
|
|||
|
return book1.getTitle().compareTo(book2.getTitle());
|
|||
|
};
|
|||
|
|
|||
|
LAMBDA EXPRESSIONS AND ANONYMOUS INNER CLASSES
|
|||
|
-
|
|||
|
|
|||
|
In Android, recall that the setOnClickListener() method takes a
|
|||
|
listener as its argument. It takes an object that implements
|
|||
|
View.OnClickListener.
|
|||
|
|
|||
|
-
|
|||
|
|
|||
|
The listener can be implemented as an anonymous inner class, which
|
|||
|
puts the implementation of the listeners’ methods right where you
|
|||
|
want to see them.
|
|||
|
|
|||
|
-
|
|||
|
|
|||
|
The syntax can be simplified by using lambda expressions!
|
|||
|
|
|||
|
LAMBDA EXPRESSIONS AND ANONYMOUS INNER CLASSES
|
|||
|
-
|
|||
|
|
|||
|
The listener can be implemented as an anonymous inner class
|
|||
|
Button button = (Button) findViewById(R.id.my_button);
|
|||
|
button.setOnClickListener(new View.OnClickListener() {
|
|||
|
@Override
|
|||
|
public void onClick(View v) {
|
|||
|
TextView myTextView = (TextView) findViewById(R.id.my_textview);
|
|||
|
myTextView.setText("Salam!");
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
-
|
|||
|
|
|||
|
The syntax can be simplified by using lambda
|
|||
|
expressions!
|
|||
|
Button button = (Button) findViewById(R.id.my_button);
|
|||
|
button.setOnClickListener((view) -> {
|
|||
|
TextView myTextView = (TextView) findViewById(R.id.my_textview);
|
|||
|
myTextView.setText("Salam!");
|
|||
|
});
|
|||
|
|
|||
|
my_
|
|||
|
|
|||
|
tex
|
|||
|
|
|||
|
my_
|
|||
|
but
|
|||
|
|
|||
|
tvi
|
|||
|
|
|||
|
ton
|
|||
|
|
|||
|
ew
|
|||
|
|
|||
|
DO YOU HAVE ANY
|
|||
|
QUESTIONS?
|
|||
|
|
|||
|
THANK
|
|||
|
YOU!
|
|||
|
|
|||
|
@
|
|||
|
|
|||
|
hend.alkittawi@utsa.edu
|
|||
|
|
|||
|
By Appointment
|
|||
|
Online
|
|||
|
|
|||
|
|