Lambda expression versus static method

I have a question about the possibility of reusing a lambda expression without duplicating code. For example, if I have a helper method, I can easily encode it as a static method and refer to it from other classes without duplicating code. How will this work in lambda expression? Example: I have the following static method written

public class MyUtil { public static int doubleMe(int x) { return x * 2; } } 

I can reuse the same method without duplicating code in multiple places throughout the project

 public class A { public void someOtherCalculation() { MyUtil.doubleMe(5); } } public class B { public void myCalculation() { MyUtil.doubleMe(3); } } 

How it works, when it comes to the lambda function, write the function once and use it in several classes.

 Function<Integer, Integer> doubleFunction = x -> x * 2; 

In my example, where would I write the above lambda function and how would I repeat its use in classes A and B?

+5
source share
4 answers

Where would I write the above lambda function

Since your function does not refer to any fields, it is advisable to place it in a static final field:

 class Utility { public static final Function<Integer,Integer> doubleFunction = x -> x * 2; } 

how to repeat use in classes A and B?

You would name it as Utility.doubleFunction and pass it in the context where necessary:

 callMethodWithLambda(Utility.doubleFunction); 

Note that method references allow you to define a function and use it as if it were a lambda:

 class Utility { public static Integer doubleFunction(Integer x) { return x*2; } } ... callMethodWithLambda(Utility::doubleFunction); 

This approach is very flexible because it allows you to reuse the same code in multiple contexts as needed.

+6
source

Indeed, anonymous functions are intended for cases where code reuse is not required.

A dumb example, but say you use map to add two to each number in the list. If this is a general action that you might need everywhere, a static function that adds two to a number makes more sense than writing the same lambda around the world.

If, however, you have one function that adds two to the list, it makes sense to define the โ€œadd twoโ€ function locally as lambda so that you do not connect your class with code that is no longer needed,

When writing Clojure, which makes extensive use of higher-order functions, it is quite common for me to create local anonymous functions that remove code in the "full" function that I write. The vast majority of these anonymous functions will be insensitive in the "global" realm (or class); moreover, they usually have closures in local variables, so they cannot be global.

+3
source

With lambda expressions, you donโ€™t have to worry about reuse (in fact, most lambdas are not reused). If you want the Function pointer to point to this method, you can declare one of them below:

 Function<Integer, Integer> doubleFunction = MyUtil::doubleMe; 

And pass it to any method or thread to use / map, for example:

 public static void consume(Function<Integer, Integer> consumer, int value){ System.out.println(consumer.apply(value)); } public static void main(String[] args) throws Exception{ Function<Integer, Integer> doubleFunction = MyUtil::doubleMe; consume(doubleFunction, 5); } 
+2
source

Unlike other answers. I would like to answer your question on TDD.

IF your doubleMe as simple as you wrote, that is, clrealy you should stop abusing the reference to the method expression and just call it directly as a call to the general method.

IF your doubleMe so complex that you want to test doubleMe independent, you need to do an implicit explanation of the dependencies by injecting the dependencies to see if they can work together with their cummunication protocols. But java cannot reference the derctly method, except that you use api reflection of Method / using an anonymous class that implements SAM , which delegates the request to the method earlier in jdk-8. What a joyful thing - you can link to the method expression link to the functional interface in jdk-8. so you can make explicit dependencies explicit using the functional interface, then I would like to write some communication protocol tests, as shown below:

 @Test void applyingMultiplicationWhenCalculating???(){ IntUnaryOperator multiplication = mock(IntUnaryOperator.class); B it = new B(multiplication); it.myCalculation(); verify(multiplication).applyAsInt(3); } 

And then your classes, like B , for example, use dependency injection, as shown below:

 public class B { IntUnaryOperator multiplication; public B(IntUnaryOperator multiplication){ this.multiplication = multiplication; } public void myCalculation() { multiplication.applyAsInt(3); } } 

THEN, you can reuse a method by referencing a method expression reference to a functional interface, as shown below:

 A a = new A(MyUtil::doubleMe); B b = new B(MyUtil::doubleMe); 
+2
source

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


All Articles