I am looking at the following Stack Overflow answer:
How to change Spring's #Scheduled fixedDelay at runtime
And in the code there is the following line:
schedulerFuture = taskScheduler.schedule(() -> { }, this);
I would like to know what the lambda () -> {} means in that code. I need to write it without using lambdas.
Its a Runnable with an empty run definition. The anonymous class representation of this would be:
new Runnable() {
#Override public void run() {
// could have done something here
}
}
Lamda expression is an anonymous function that allows you to pass methods as arguments or simply, a mechanism that helps you remove a lot of boilerplate code. They have no access modifier(private, public or protected), no return type declaration and no name.
Lets take a look at this example.
(int a, int b) -> {return a > b}
In your case, you can do something like below:
schedulerFuture = taskScheduler.schedule(new Runnable() {
#Override
public void run() {
// task details
}
}, this);
For lambdas:
Left side is arguments, what you take. Enclosed in () are all the arguments this function takes
-> indicates that it's a function that takes what's on the left and passes it on to the right for processing
Right side is the body - what the lambda does. Enclosed in {} is everything this function does
After you figure that out you only need to know that that construction passes an instance of matching class (look at what's the expected argument type in the schedule() call) with it's only method doing exactly the same as the lambda expression we've just analyzed.
Lambda expressions basically express instances of functional interfaces.
In a way Lambda expression will be: (lambda operator params) -> {body}
() -> System.out.println("This means Lambda expression is not taking any parameters");
(p) -> System.out.println("Lambda expression with one parameter: " + p);
Related
This question already has answers here:
Java Pass Method as Parameter
(17 answers)
Closed 8 years ago.
In Java, how can one pass a function as an argument of another function?
Java 8 and above
Using Java 8+ lambda expressions, if you have a class or interface with only a single abstract method (sometimes called a SAM type), for example:
public interface MyInterface {
String doSomething(int param1, String param2);
}
then anywhere where MyInterface is used, you can substitute a lambda expression:
class MyClass {
public MyInterface myInterface = (p1, p2) -> { return p2 + p1; };
}
For example, you can create a new thread very quickly:
new Thread(() -> someMethod()).start();
And use the method reference syntax to make it even cleaner:
new Thread(this::someMethod).start();
Without lambda expressions, these last two examples would look like:
new Thread(new Runnable() { someMethod(); }).start();
Before Java 8
A common pattern would be to 'wrap' it within an interface, like Callable, for example, then you pass in a Callable:
public T myMethod(Callable<T> func) {
return func.call();
}
This pattern is known as the Command Pattern.
Keep in mind you would be best off creating an interface for your particular usage. If you chose to go with callable, then you'd replace T above with whatever type of return value you expect, such as String.
In response to your comment below you could say:
public int methodToPass() {
// do something
}
public void dansMethod(int i, Callable<Integer> myFunc) {
// do something
}
then call it, perhaps using an anonymous inner class:
dansMethod(100, new Callable<Integer>() {
public Integer call() {
return methodToPass();
}
});
Keep in mind this is not a 'trick'. It's just java's basic conceptual equivalent to function pointers.
You could use Java reflection to do this. The method would be represented as an instance of java.lang.reflect.Method.
import java.lang.reflect.Method;
public class Demo {
public static void main(String[] args) throws Exception{
Class[] parameterTypes = new Class[1];
parameterTypes[0] = String.class;
Method method1 = Demo.class.getMethod("method1", parameterTypes);
Demo demo = new Demo();
demo.method2(demo, method1, "Hello World");
}
public void method1(String message) {
System.out.println(message);
}
public void method2(Object object, Method method, String message) throws Exception {
Object[] parameters = new Object[1];
parameters[0] = message;
method.invoke(object, parameters);
}
}
Lambda Expressions
To add on to jk.'s excellent answer, you can now pass a method more easily using Lambda Expressions (in Java 8). First, some background. A functional interface is an interface that has one and only one abstract method, although it can contain any number of default methods (new in Java 8) and static methods. A lambda expression can quickly implement the abstract method, without all the unnecessary syntax needed if you don't use a lambda expression.
Without lambda expressions:
obj.aMethod(new AFunctionalInterface() {
#Override
public boolean anotherMethod(int i)
{
return i == 982
}
});
With lambda expressions:
obj.aMethod(i -> i == 982);
Here is an excerpt from the Java tutorial on Lambda Expressions:
Syntax of Lambda Expressions
A lambda expression consists of the following:
A comma-separated list of formal parameters enclosed in parentheses. The CheckPerson.test method contains one parameter, p,
which represents an instance of the Person class.Note: You
can omit the data type of the parameters in a lambda expression. In
addition, you can omit the parentheses if there is only one parameter.
For example, the following lambda expression is also valid:
p -> p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25
The arrow token, ->
A body, which consists of a single expression or a statement block. This example uses the following expression:
p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25
If you specify a single expression, then the Java runtime evaluates the expression and then returns its value. Alternatively,
you can use a return statement:
p -> {
return p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25;
}
A return statement is not an expression; in a lambda expression, you must enclose statements in braces ({}). However, you do not have
to enclose a void method invocation in braces. For example, the
following is a valid lambda expression:
email -> System.out.println(email)
Note that a lambda expression looks a lot like a method declaration;
you can consider lambda expressions as anonymous methods—methods
without a name.
Here is how you can "pass a method" using a lambda expression:
Note: this uses a new standard functional interface, java.util.function.IntConsumer.
class A {
public static void methodToPass(int i) {
// do stuff
}
}
import java.util.function.IntConsumer;
class B {
public void dansMethod(int i, IntConsumer aMethod) {
/* you can now call the passed method by saying aMethod.accept(i), and it
will be the equivalent of saying A.methodToPass(i) */
}
}
class C {
B b = new B();
public C() {
b.dansMethod(100, j -> A.methodToPass(j)); //Lambda Expression here
}
}
The above example can be shortened even more using the :: operator.
public C() {
b.dansMethod(100, A::methodToPass);
}
Thanks to Java 8 you don't need to do the steps below to pass a function to a method, that's what lambdas are for, see Oracle's Lambda Expression tutorial. The rest of this post describes what we used to have to do in the bad old days in order to implement this functionality.
Typically you declare your method as taking some interface with a single method, then you pass in an object that implements that interface. An example is in commons-collections, where you have interfaces for Closure, Transformer, and Predicate, and methods that you pass implementations of those into. Guava is the new improved commons-collections, you can find equivalent interfaces there.
So for instance, commons-collections has org.apache.commons.collections.CollectionUtils, which has lots of static methods that take objects passed in, to pick one at random, there's one called exists with this signature:
static boolean exists(java.util.Collection collection, Predicate predicate)
It takes an object that implements the interface Predicate, which means it has to have a method on it that takes some Object and returns a boolean.
So I can call it like this:
CollectionUtils.exists(someCollection, new Predicate() {
public boolean evaluate(Object object) {
return ("a".equals(object.toString());
}
});
and it returns true or false depending on whether someCollection contains an object that the predicate returns true for.
Anyway, this is just an example, and commons-collections is outdated. I just forget the equivalent in Guava.
Java supports closures just fine. It just doesn't support functions, so the syntax you're used to for closures is much more awkward and bulky: you have to wrap everything up in a class with a method. For example,
public Runnable foo(final int x) {
return new Runnable() {
public void run() {
System.out.println(x);
}
};
}
Will return a Runnable object whose run() method "closes over" the x passed in, just like in any language that supports first-class functions and closures.
I used the command pattern that #jk. mentioned, adding a return type:
public interface Callable<I, O> {
public O call(I input);
}
I know this is a rather old post but I have another slightly simpler solution.
You could create another class within and make it abstract. Next make an Abstract method name it whatever you like. In the original class make a method that takes the new class as a parameter, in this method call the abstract method. It will look something like this.
public class Demo {
public Demo(/.../){
}
public void view(Action a){
a.preform();
}
/**
* The Action Class is for making the Demo
* View Custom Code
*/
public abstract class Action {
public Action(/.../){
}
abstract void preform();
}
}
Now you can do something like this to call a method from within the class.
/...
Demo d = new Demo;
Action a = new Action() {
#Override
void preform() {
//Custom Method Code Goes Here
}
};
/.../
d.view(a)
Like I said I know its old but this way I think is a little easier. Hope it helps.
Java does not (yet) support closures. But there are other languages like Scala and Groovy which run in the JVM and do support closures.
This question already has answers here:
Lambda 'special void-compatibility rule' - statement expression
(3 answers)
Why do Consumers accept lambdas with statement bodies but not expression bodies?
(3 answers)
Why does a Java method reference with return type match the Consumer interface?
(2 answers)
Consumer lambda in Java 8 [duplicate]
(2 answers)
Closed 4 years ago.
Given this method:
private static Integer return0() {
return 0;
}
I discovered a weird property of the following lambda expression:
() -> return0();
Does it actually return the value from the function it calls (which would make it a Supplier-Interface) or does it not return the value but only calls the function and returns void (which would make it a Runnable-Interface). Intuitively, I would expect the first case to be correct but could live with the second.
When trying to assign the statement:
Supplier<Integer> supplier2 = () -> return0();
Runnable runnable2 = () -> return0();
It turns out both lines do compile! Why would they allow that? It is completely ambiguous and really confusing!
EDIT:
Here is more code to demonstrate what I mean by confusing/ambigous:
public static void main(String[] args) {
callMe(() -> return0());
}
private static Integer return0() {
return 0;
}
private static void callMe(Supplier<Integer> supplier) {
System.out.println("supplier!");
}
private static void callMe(Runnable runnable) {
System.out.println("runnable!");
}
This all compiles well and upon execution prints "supplier!". I do not find it particularly intuitive that the first method is chosen but rather arbitrary.
The relevant part of the spec is Sec 15.27.3 (emphasis mine):
A lambda expression is congruent with a function type if all of the following are true:
The function type has no type parameters.
The number of lambda parameters is the same as the number of parameter types of the function type.
If the lambda expression is explicitly typed, its formal parameter types are the same as the parameter types of the function type.
If the lambda parameters are assumed to have the same types as the function type's parameter types, then:
If the function type's result is void, the lambda body is either a statement expression (§14.8) or a void-compatible block.
If the function type's result is a (non-void) type R, then either i) the lambda body is an expression that is compatible with R in an assignment context, or ii) the lambda body is a value-compatible block, and each result expression (§15.27.2) is compatible with R in an assignment context.
Your lambda body is a statement expression, and the function type's result is void.
In other words, it would be fine for you to write:
return0();
and ignore the return value in "regular" code, so it's fine to ignore the result value in a lambda too.
In terms of the question over ambiguity of overloads, there is no ambiguity in this case (it's easy to construct a case where there is ambiguity, e.g. another overload with a parameter that looks like Supplier but is a different interface, i.e. takes no parameters, returns a value).
You would have to read the spec in detail for the precise reasoning, but I think the most relevant section is Sec 15.12, which describes method invocation expressions, and the most useful quote from that is in Sec 15.12.2.5, which deals with selecting the most-specific overload:
The informal intuition is that one method is more specific than another if any invocation handled by the first method could be passed on to the other one without a compile-time error.
You can use a Supplier<Integer> in place of a Runnable (with a bit of a hand-wavy fudge) because you can simply ignore the return value; you can't use a Runnable in place of a Supplier<Integer> because it doesn't have a return value.
So a method taking the Supplier<Integer> is more specific than the method taking the Runnable, hence that is the one which is invoked.
If you get confused with lambda expressions, replace them with anonymous classes for a better understanding (IntelliJ IDEA can easily help you with that). The following code snippets are completely valid:
Supplier<Integer> supplier2 = () -> return0() is equivalent to:
Supplier<Integer> supplier2 = new Supplier<Integer>() {
#Override
public Integer get() {
return return0();
}
};
Runnable runnable2 = () -> return0() is equivalent to:
Runnable runnable2 = new Runnable() {
#Override
public void run() {
return0();
}
};
public static void main(String[] args) throws Exception
{
Supplier<Integer> consumer2 = Trial::return0;
Runnable runnable2 = Trial::return0;
run(Trial::return0);
}
private static Integer return0() {
return 0;
}
private static int run(Supplier<Integer> a)
{
System.out.println("supplier");
return a.get();
}
private static void run(Runnable r)
{
System.out.println("runnable");
r.run();
}
As far as method overloading is concerned, this code in class Trial prints "supplier".
I'm trying to create a method that allows me to make use of what I believe is called lambdas, to execute a method over a series of connections.
Here's my code that I've come up with after some research, but it doesn't work:
performGlobalAction(()->{
// doSomething();
});
You'll also need to see the method I would assume:
private <T> void performGlobalAction(Callable<T> action) {
for(int i = 0; i < connectionList.size(); i++) {
connectionList.get(i).performAction(action);
}
}
This provides the following error:
The method performAction(Callable<T>) in the type Connection is not
applicable for the arguments (() -> {})
The goal of this method is to allow myself to construct a method "on the go" without creating a void for it.
Is this possible? It seems like I've used plenty of statements that have done this before. It seems like this is actually exactly how lambdas statements work.
The call method of the Callable interface returns a value of type T. Your lambda is simply shorthand for the call method, and likewise should return a T value.
Any interface that meets the requirements of a FunctionalInterface can be substituted by a lambda expression. Such an interface will have a single abstract method, one with no default implementation. For your question, the interface is Callable, and the abstract method is call. The lambda expression then acts as the body of that abstract method in an anonymous implementation of that interface.
Let's take as an example a method doStuff(Callable<Integer> stuff). To satisfy this interface, you could give an anonymous class:
doStuff(new Callable<Integer>(){
public Integer call(){
return 5;
}
});
Or you could use a lambda:
doStuff( () -> {
return 5;
} );
Or even more succinctly:
doStuff( () -> 5 );
If your method doesn't have a return type, perhaps Runnable would be a better fit.
See also: Lambda Expressions (Oracle) - 'Use Standard Functional Interfaces with Lambda Expressions'
I am trying to use java 8 features. While reading official tutorial I came across this code
static void invoke(Runnable r) {
r.run();
}
static <T> T invoke(Callable<T> c) throws Exception {
return c.call();
}
and there was a question:
Which method will be invoked in the following statement?"
String s = invoke(() -> "done");
and answer to it was
The method invoke(Callable<T>) will be invoked because that method returns a value; the method invoke(Runnable) does not. In this case, the type of the lambda expression () -> "done" is Callable<T>.
As I understand since invoke is expected to return a String, it calls Callable's invoke. But, not sure how exactly it works.
Let's take a look at the lambda
invoke(() -> "done");
The fact that you only have
"done"
makes the lambda value compatible. The body of the lambda, which doesn't appear to be an executable statement, implicitly becomes
{ return "done";}
Now, since Runnable#run() doesn't have a return value and Callable#call() does, the latter will be chosen.
Say you had written
invoke(() -> System.out.println());
instead, the lambda would be resolved to an instance of type Runnable, since there is no expression that could be used a return value.
This question already has answers here:
Java Pass Method as Parameter
(17 answers)
Closed 8 years ago.
In Java, how can one pass a function as an argument of another function?
Java 8 and above
Using Java 8+ lambda expressions, if you have a class or interface with only a single abstract method (sometimes called a SAM type), for example:
public interface MyInterface {
String doSomething(int param1, String param2);
}
then anywhere where MyInterface is used, you can substitute a lambda expression:
class MyClass {
public MyInterface myInterface = (p1, p2) -> { return p2 + p1; };
}
For example, you can create a new thread very quickly:
new Thread(() -> someMethod()).start();
And use the method reference syntax to make it even cleaner:
new Thread(this::someMethod).start();
Without lambda expressions, these last two examples would look like:
new Thread(new Runnable() { someMethod(); }).start();
Before Java 8
A common pattern would be to 'wrap' it within an interface, like Callable, for example, then you pass in a Callable:
public T myMethod(Callable<T> func) {
return func.call();
}
This pattern is known as the Command Pattern.
Keep in mind you would be best off creating an interface for your particular usage. If you chose to go with callable, then you'd replace T above with whatever type of return value you expect, such as String.
In response to your comment below you could say:
public int methodToPass() {
// do something
}
public void dansMethod(int i, Callable<Integer> myFunc) {
// do something
}
then call it, perhaps using an anonymous inner class:
dansMethod(100, new Callable<Integer>() {
public Integer call() {
return methodToPass();
}
});
Keep in mind this is not a 'trick'. It's just java's basic conceptual equivalent to function pointers.
You could use Java reflection to do this. The method would be represented as an instance of java.lang.reflect.Method.
import java.lang.reflect.Method;
public class Demo {
public static void main(String[] args) throws Exception{
Class[] parameterTypes = new Class[1];
parameterTypes[0] = String.class;
Method method1 = Demo.class.getMethod("method1", parameterTypes);
Demo demo = new Demo();
demo.method2(demo, method1, "Hello World");
}
public void method1(String message) {
System.out.println(message);
}
public void method2(Object object, Method method, String message) throws Exception {
Object[] parameters = new Object[1];
parameters[0] = message;
method.invoke(object, parameters);
}
}
Lambda Expressions
To add on to jk.'s excellent answer, you can now pass a method more easily using Lambda Expressions (in Java 8). First, some background. A functional interface is an interface that has one and only one abstract method, although it can contain any number of default methods (new in Java 8) and static methods. A lambda expression can quickly implement the abstract method, without all the unnecessary syntax needed if you don't use a lambda expression.
Without lambda expressions:
obj.aMethod(new AFunctionalInterface() {
#Override
public boolean anotherMethod(int i)
{
return i == 982
}
});
With lambda expressions:
obj.aMethod(i -> i == 982);
Here is an excerpt from the Java tutorial on Lambda Expressions:
Syntax of Lambda Expressions
A lambda expression consists of the following:
A comma-separated list of formal parameters enclosed in parentheses. The CheckPerson.test method contains one parameter, p,
which represents an instance of the Person class.Note: You
can omit the data type of the parameters in a lambda expression. In
addition, you can omit the parentheses if there is only one parameter.
For example, the following lambda expression is also valid:
p -> p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25
The arrow token, ->
A body, which consists of a single expression or a statement block. This example uses the following expression:
p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25
If you specify a single expression, then the Java runtime evaluates the expression and then returns its value. Alternatively,
you can use a return statement:
p -> {
return p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25;
}
A return statement is not an expression; in a lambda expression, you must enclose statements in braces ({}). However, you do not have
to enclose a void method invocation in braces. For example, the
following is a valid lambda expression:
email -> System.out.println(email)
Note that a lambda expression looks a lot like a method declaration;
you can consider lambda expressions as anonymous methods—methods
without a name.
Here is how you can "pass a method" using a lambda expression:
Note: this uses a new standard functional interface, java.util.function.IntConsumer.
class A {
public static void methodToPass(int i) {
// do stuff
}
}
import java.util.function.IntConsumer;
class B {
public void dansMethod(int i, IntConsumer aMethod) {
/* you can now call the passed method by saying aMethod.accept(i), and it
will be the equivalent of saying A.methodToPass(i) */
}
}
class C {
B b = new B();
public C() {
b.dansMethod(100, j -> A.methodToPass(j)); //Lambda Expression here
}
}
The above example can be shortened even more using the :: operator.
public C() {
b.dansMethod(100, A::methodToPass);
}
Thanks to Java 8 you don't need to do the steps below to pass a function to a method, that's what lambdas are for, see Oracle's Lambda Expression tutorial. The rest of this post describes what we used to have to do in the bad old days in order to implement this functionality.
Typically you declare your method as taking some interface with a single method, then you pass in an object that implements that interface. An example is in commons-collections, where you have interfaces for Closure, Transformer, and Predicate, and methods that you pass implementations of those into. Guava is the new improved commons-collections, you can find equivalent interfaces there.
So for instance, commons-collections has org.apache.commons.collections.CollectionUtils, which has lots of static methods that take objects passed in, to pick one at random, there's one called exists with this signature:
static boolean exists(java.util.Collection collection, Predicate predicate)
It takes an object that implements the interface Predicate, which means it has to have a method on it that takes some Object and returns a boolean.
So I can call it like this:
CollectionUtils.exists(someCollection, new Predicate() {
public boolean evaluate(Object object) {
return ("a".equals(object.toString());
}
});
and it returns true or false depending on whether someCollection contains an object that the predicate returns true for.
Anyway, this is just an example, and commons-collections is outdated. I just forget the equivalent in Guava.
Java supports closures just fine. It just doesn't support functions, so the syntax you're used to for closures is much more awkward and bulky: you have to wrap everything up in a class with a method. For example,
public Runnable foo(final int x) {
return new Runnable() {
public void run() {
System.out.println(x);
}
};
}
Will return a Runnable object whose run() method "closes over" the x passed in, just like in any language that supports first-class functions and closures.
I used the command pattern that #jk. mentioned, adding a return type:
public interface Callable<I, O> {
public O call(I input);
}
I know this is a rather old post but I have another slightly simpler solution.
You could create another class within and make it abstract. Next make an Abstract method name it whatever you like. In the original class make a method that takes the new class as a parameter, in this method call the abstract method. It will look something like this.
public class Demo {
public Demo(/.../){
}
public void view(Action a){
a.preform();
}
/**
* The Action Class is for making the Demo
* View Custom Code
*/
public abstract class Action {
public Action(/.../){
}
abstract void preform();
}
}
Now you can do something like this to call a method from within the class.
/...
Demo d = new Demo;
Action a = new Action() {
#Override
void preform() {
//Custom Method Code Goes Here
}
};
/.../
d.view(a)
Like I said I know its old but this way I think is a little easier. Hope it helps.
Java does not (yet) support closures. But there are other languages like Scala and Groovy which run in the JVM and do support closures.