Passing
Lambda Expressions as Arguments
As explained earlier, a
lambda expression can be used in any context that provides a target type. One
of these is when a lambda expression is passed as an argument. In fact, passing
a lambda expression as an argument is a common use of lambdas. Moreover, it is
a very powerful use because it gives you a way to pass executable code as an
argument to a method. This greatly enhances the expressive power of Java.
To pass a lambda expression
as an argument, the type of the parameter receiving the lambda expression
argument must be of a functional interface type compatible with the lambda.
Although using a lambda expression as an argument is straightforward, it is
still helpful to see it in action. The following program demonstrates the
process:
// Use lambda expressions as an argument to a
method.
interface StringFunc { String func(String n);
}
class LambdasAsArgumentsDemo {
//This method has a functional interface as the
type of
//its first parameter. Thus, it can be passed a
reference to any instance of that interface, including the instance created by
a lambda expression.
//The second parameter specifies the string to
operate on.
static String stringOp(StringFunc sf, String s)
{
return sf.func(s);
}
public static void main(String args[])
{
String inStr = "Lambdas add power to
Java"; String outStr;
System.out.println("Here is input string:
" + inStr);
//Here, a simple expression lambda that
uppercases a string is passed to stringOp( ).
outStr = stringOp((str) ->
str.toUpperCase(), inStr);
System.out.println("The string in
uppercase: " + outStr);
// This passes a block lambda that removes
spaces.
outStr = stringOp((str) -> {
String result = ""; int i;
for(i = 0; i < str.length(); i++)
if(str.charAt(i) != ' ')
result += str.charAt(i);
return
result; }, inStr);
System.out.println("The string with spaces
removed: " + outStr);
//Of course, it is also possible to pass a StringFunc
instance created by an earlier lambda expression. For example, after this
declaration executes, reverse refers to an instance of StringFunc.
StringFunc reverse = (str) -> { String
result = "";
int i;
for(i = str.length()-1; i >= 0; i--) result
+= str.charAt(i);
return result;
};
//Now, reverse can be passed as the first
parameter to stringOp()
//since it refers to a StringFunc object.
System.out.println("The string reversed:
" +
stringOp(reverse, inStr));
}
}
The output is shown here:
Here is input string: Lambdas add power to Java
The string in uppercase: LAMBDAS ADD POWER TO
JAVA
The string with spaces removed:
LambdasaddpowertoJava
The string reversed: avaJ ot rewop dda sadbmaL
In the program, first notice
the stringOp( ) method. It has two
parameters. The first is of type StringFunc,
which is a functional interface. Thus, this parameter can receive a reference
to any instance of StringFunc,
including one created by a lambda expression. The second argument of stringOp( ) is of type String, and this is the string operated
on.
Next, notice the first call
to stringOp( ), shown again here:
outStr = stringOp((str) ->
str.toUpperCase(), inStr);
Here, a simple expression
lambda is passed as an argument. When this occurs, an instance of the
functional interface StringFunc is
created and a reference to that object is passed to the first parameter of stringOp( ). Thus, the lambda code,
embedded in a class instance, is passed to the method. The target type context
is determined by the type of parameter. Because the lambda expression is
compatible with that type, the call is valid. Embedding simple lambdas, such as
the one just shown, inside a method call is often a convenient
technique—especially when the lambda expression is intended for a single use.
Next, the program passes a
block lambda to stringOp( ). This
lambda removes spaces from a string. It is shown again here:
outStr = stringOp((str) -> {
String result = ""; int i;
for(i = 0; i < str.length(); i++)
if(str.charAt(i) != ' ')
result += str.charAt(i);
return
result; }, inStr);
Although this uses a block
lambda, the process of passing the lambda expression is the same as just
described for the simple expression lambda. In this case, however, some
programmers will find the syntax a bit awkward.
When a block lambda seems
overly long to embed in a method call, it is an easy matter to assign that
lambda to a functional interface variable, as the previous examples have done.
Then, you can simply pass that reference to the method. This technique is shown
at the end of the program. There, a block lambda is defined that reverses a
string. This lambda is assigned to reverse,
which is a reference to a StringFunc
instance. Thus, reverse can be used
as an argument to the first parameter of stringOp(
). The program then calls stringOp(
), passing in reverse and the
string on which to operate. Because the instance obtained by the evaluation of each lambda expression is an
implementation of StringFunc, each
can be used as the first parameter to stringOp(
).
One last point: In addition
to variable initialization, assignment, and argument passing, the following
also constitute target type contexts: casts, the ? operator, array initializers, return statements, and lambda expressions, themselves.
Related Topics
Privacy Policy, Terms and Conditions, DMCA Policy and Compliant
Copyright © 2018-2023 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.