Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

lambda expression vs static method

I had a question about reusability of lambda expression without code duplication. For example if I have a helper method I can easily code it as a static method and can refer to it from other classes without code duplication. How would 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 code duplication in multiple places across the project

public class A {

    public void someOtherCalculation() {
        MyUtil.doubleMe(5);
    }
}

public class B {

    public void myCalculation() {
        MyUtil.doubleMe(3);
    }
}

How would it work when it comes to a lambda function, write the function once and use the same at multiple class.

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

In my example, where would I write the above lambda function and how would I reuse the same in class A and B ?

like image 855
Nova Guy Avatar asked May 29 '17 17:05

Nova Guy


People also ask

Can we use lambda expression for static method?

A static method reference allows us to use a static method as a lambda expression. The static methods can be defined in a class, an interface, or an enum. The following code defines two lambda expressions.

Are lambda functions static?

What would it mean for a lambda to be static? You can't declare the lambda expression static. You can only declare the variable comp static. In which case it means the same as for any variable.

What are the disadvantages of lambda expression?

The big paradox of lambdas is that they are so syntactically simple to write and so tough to understand if you're not used to them. So if you have to quickly determine what the code is doing, the abstraction brought in by lambdas, even as it simplifies the Java syntax, will be hard to understand quickly and easily.

Why is static method better?

They are faster — Static methods are slightly faster than instance methods because in instance methods, you are also working with an implicit this parameter. Eliminating that parameter gives a slight performance boost in most programming languages.


4 Answers

Where would I write the above lambda function

Since your function does not reference any fields, it is appropriate to put it in a static final field:

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

how would I reuse the same in class A and B?

You would refer to it as Utility.doubleFunction, and pass it in the context where it is required:

callMethodWithLambda(Utility.doubleFunction);

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

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

This approach is very flexible, because it lets you reuse the same code in multiple contexts as you find appropriate.

like image 120
Sergey Kalinichenko Avatar answered Oct 05 '22 07:10

Sergey Kalinichenko


With lambda expressions, you don't need to worry about reusability (in fact, most of the lambdas are not being re-used at all). If you want a Function pointer to point to this method the you can declare one like below:

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

And pass it to any method or stream to apply/map, e.g.:

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);
}
like image 25
Darshan Mehta Avatar answered Oct 05 '22 07:10

Darshan Mehta


Really, anonymous functions are for cases where code reuse isn't necessary.

Dumb example, but say you're using map to add two to every number in a list. If this is a common action that you may need all over the place, a static function that adds two to a number makes more sense than writing the same lambda everywhere.

If, however you have a single function that adds two to a list, it makes more sense to define the "add two" function locally as a lambda so you dont plug up your class with code that isn't needed anywhere else.

When writing Clojure, which makes extensive use of higher-order functions, it's pretty common for me to create local anonymous functions that tidy up the code in the "full" function that I'm writing. The vast majority of these anonymous functions would be non-sensical in the "global" scope (or class-scope); especially since they usually have closures over local variables, so they couldn't be global anyways.

like image 36
Carcigenicate Avatar answered Oct 05 '22 09:10

Carcigenicate


Different from other answers. I'd like to answer your question in TDD way.

IF your doubleMe is so simple as you have wrote, that is clrealy you should stop abusing method expression reference and just call it directly as a common method invocation.

IF your doubleMe is so complicated that you want to test doubleMe independent , you need to make implicit dependencies explicity by dependency injection to testing whether they can working together by their cummunication protocols. But java can't refer a method dierctly except you using reflection api Method/using a anonymous class that implements SAM interface which delegates request to a method before in jdk-8. What the happy thing is you can refer a method expression reference to a functional interface in jdk-8. so you can make implicit dependencies explicit by using functional interface, then I would like write some communication protocol test as 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 as B applied dependency injection is more like as 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 refer a method expression reference to a functional interface as below:

A a = new A(MyUtil::doubleMe);
B b = new B(MyUtil::doubleMe);
like image 43
holi-java Avatar answered Oct 05 '22 08:10

holi-java