college/Summer-2024/CS-3443/Slides/txt/29_Lambda Expressions.txt

633 lines
9.6 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Application
Programming
Hend Alkittawi
Lambda Expressions
Introduction to Lambda Expressions
in Java
INTRODUCTION
-
To understand Javas 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; Javas 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