How to pass and use arbitrary lambda functions as a parameter

I am well versed in lambda functions in Lisp. Java doesn't seem to be as flexible as Lisp. How do I think of lambdas in Java? Given the code below, how can I do this?

public class Draw { GraphicsContext gc; static void draw(double x, double y, double w, double h, boolean drawRect) { if (drawRect) { gc.fillRect(x, y, w, h); } else { gc.strokeRect(x, y, w, h); } } // How do I do that? static void drawWithLambda(double x, double y, double w, double h /**, lambda */) { lambda(x, y, w, h); } public static void main(String[] args) { draw(0, 0, 50, 50, false); // OK drawWithLambda(0, 0, 50, 50, GraphicsContext::fillRect); // Ok? } } 
+5
source share
2 answers

You must specify the type of functional interface that implements the argument to the lambda method:

 drawWithLambda(double x, double y, double w, double h, SomeFuncInterface lambda) { lambda.someMethod (x, y, w, h); // someMethod is the single method that // SomeFuncInterface implements } 

To make this line work

 drawWithLambda(0, 0, 50, 50, GraphicsContext::fillRect); 

the fillRect of GraphicsContext method must be compatible with the signature of the SomeFuncInterface functional interface SomeFuncInterface .

BTW, GraphicsContext::fillRect is a method reference, not a lambda expression. You can pass either lambda expressions, method references, or any other implementation of the functional interface (a regular class instance, an anonymous class instance, etc.).

+3
source

Lambda in Java works in conjunction with the concept of a functional interface .

A typical example is Function . Function - a functional interface whose functional method apply is a method that takes one argument and returns the result.

You can create your own functional interface that defines a functional method with 4 parameters and without a return type, for example:

 @FunctionalInterface interface RectangleDrawer { void draw(double x, double y, double w, double h); } 

( FunctionalInterface annotation is not strictly necessary, but gives clear intent).

Then you can create a lambda that matches the contract of this functional interface. Typical lambda syntax is (method arguments) -> (lambda body) . In this example, it will be: (x, y, w, h) -> gc.fillRect(x, y, w, h) . This compiles because the lambda declares 4 arguments and does not have a return type, so it can be represented as the RectangleDrawer function method defined earlier.

Example:

 static GraphicsContext gc; public static void main(String[] args) { draw(0, 0, 50, 50, (x, y, w, h) -> gc.fillRect(x, y, w, h)); draw(0, 0, 50, 50, (x, y, w, h) -> gc.strokeRect(x, y, w, h)); } static void draw(double x, double y, double w, double h, RectangleDrawer drawer) { drawer.draw(x, y, w, h); } 

In this particular case, you can use the link to create a lambda using the :: operator, which allows you to write simpler code:

 static GraphicsContext gc; public static void main(String[] args) { draw(0, 0, 50, 50, gc::fillRect); draw(0, 0, 50, 50, gc::strokeRect); } static void draw(double x, double y, double w, double h, RectangleDrawer drawer) { drawer.draw(x, y, w, h); } 
+3
source

Source: https://habr.com/ru/post/1233122/


All Articles