Different behavior between lambda expression and method reference by instantiation

method reference in java 8 geeksforgeeks
method reference vs lambda
java 8 method reference with parameters
java method reference constructor
lambda expression java
java method reference with multiple parameters
java lambda as parameter
method reference java 8 example mkyong

As I know lambda expression can be replaced by method reference without any issues. My IDEs say the same, but the following example shows the opposite. The method reference clearly returns the same object, where as lambda expression returns new objects each time.

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Instance {

    int member;

    Instance set(int value){
        this.member = value;
        return this;
    }

    @Override
    public String toString() {
        return member + "";
    }

    public static void main(String[] args) {

        Stream<Integer> stream1 = Stream.of(1, 2, 3, 4);
        Stream<Integer> stream2 = Stream.of(1, 2, 3, 4);

        List<Instance> collect1 = stream1.map(i -> new Instance().set(i)).collect(Collectors.toList());
        List<Instance> collect2 = stream2.map(new Instance()::set).collect(Collectors.toList());

        System.out.println(collect1);
        System.out.println(collect2);
    }
}

Here is my output:

[1, 2, 3, 4]
[4, 4, 4, 4]

The timing of method reference expression evaluation differs from which of lambda expressions. With a method reference that has an expression (rather than a type) preceding the :: the subexpression is evaluated immediately and the result of evaluation is stored and reused then. So here :

new Instance()::set

new Instance() is evaluated a single time.

From 15.12.4. Run-Time Evaluation of Method Invocation (emphasis is mine) :

The timing of method reference expression evaluation is more complex than that of lambda expressions (§15.27.4). When a method reference expression has an expression (rather than a type) preceding the :: separator, that subexpression is evaluated immediately. The result of evaluation is stored until the method of the corresponding functional interface type is invoked; at that point, the result is used as the target reference for the invocation. This means the expression preceding the :: separator is evaluated only when the program encounters the method reference expression, and is not re-evaluated on subsequent invocations on the functional interface type.

Lambda and method reference - Edouard Kaiser, Java 8 brought us the lambda expressions (and the adepts of In terms of compiler and runtime behavior (for OpenJDK), an inline lambda expression will be class, just like any other class, with its constructor and methods. In the first one, for each item in your stream, the lambda expression in your map() is creating a new Instance object. In the second one, new Instance() is being called once, before the map() starts to pass the values. If you want to use a method reference, add a constructor to Instance like this.

Your lambda expression is calling new Instance() each time it's executed. This explains why the result of its toString() is different for each element.

The method reference retains the instance off which it is referenced, such that it's similar to:

Instance instance = new Instance();
List<Instance> collect2 = stream2.map(instance::set).collect(Collectors.toList());

The result of using the method reference in this case is that the same instance is used to call set, collected at the end. The member value displayed is the one last set.


As an experiment, make these changes and observe that the instance is changing in the case of the lambda expression:

/* a random string assigned per instance */
private String uid = UUID.randomUUID().toString();

Instance set(int value) {
    this.member = value;
    System.out.println("uid: " + uid); //print the ID
    return this;
}

Java 8: Method References, Method references are a special form of the lambda expression. doing nothing other than invoking existing behavior (methods), you can achieve the same constructor method ,instance method ,java ,java 8 ,java 8 lambda  The timing of method reference expression evaluation differs from which of lambda expressions. With a method reference that has an expression (rather than a type) preceding the :: the subexpression is evaluated immediately and the result of evaluation is stored and reused then. So here : new Instance()::set . new Instance() is evaluated a single time.

The difference in the second option is, you create one single (1) instance the moment you create the Stream pipeline. When you eventually iterate over the stream elements after calling the terminal method (toList), you invoke the set method on that same instance four times, where the last value is the final one. The resulting List (collect2) contains four times the same instance.

State of the Lambda, A type like "function from a String and an Object to an int " might be expressed as 1 uses five lines of source code to encapsulate a single aspect of behavior. of this approach is that the same lambda expression can have different types in There is a special syntactic form of constructor references for arrays, which treats​  Again, the interesting aspect of this type of method reference is that the method getName is an instance method. Therefore, the target of its invocation must be an instance, which in this case is an arbitrary object being provided as the argument for the method apply in the Function interface definition.

In the first one, for each item in your stream, the lambda expression in your map() is creating a new Instance object.

In the second one, new Instance() is being called once, before the map() starts to pass the values.

If you want to use a method reference, add a constructor to Instance like this. (I actually recommend also making the Instance immutable by making member final so that you avoid confusion like this from other places, like this).

private final int member;

public Instance(int member) {
  this.member = member;
}

//remove the setter

Then change your stream processing to look like this:

List<Instance> collect2 = stream2.map(Instance::new).collect(Collectors.toList());

This way you are sure that the member is not changed once it is initialised, and you make use of method references concisely (in this case the constructor is the method reference with new).

Lambda Expressions (The Java™ Tutorials > Learning the Java , Lambda expressions let you express instances of single-method classes more What if you decide to change the Person class and add other attributes such as T . When you declare or instantiate a generic type with actual type arguments, you expressions as parameters, enabling you to customize how they behave. A Java lambda expression is an anonymous (that is, unnamed) method that can be created without belonging to any class. Instead, it is used to implement a method defined by a function interface (this interface contains one — and only one — abstract method but also can contain multiple default and static methods).

Differences between Lambda Expression and Method Reference in , Lambda expression is an anonymous method (method without a name) that has used to provide the inline implementation of a method defined  In Java 8, thanks to lambda expressions, we can do something like this. We can use methods as if they were objects, or primitive values. Java 8 Method Reference. A method reference is the shorthand syntax for a lambda expression that executes just ONE method. Here's the general syntax of a method reference: Object :: methodName

Chapter 3. Lambda expressions, But you saw that using anonymous classes to represent different behaviors is and gradually improve it using lambda expressions and method references to make it more Lambda expressions will encourage you to adopt the style of behavior it's clumsier: you provide an implementation and instantiate it directly inline. The body of an expression lambda can consist of a method call. However, if you are creating expression trees that are evaluated outside the context of the .NET common language runtime, such as in SQL Server, you should not use method calls in lambda expressions. The methods will have no meaning outside the context of the .NET common language

Lambda Expressions in Java, Parameters; Body; Variable Capture; Method Referencing Parameter Method Reference; Instance Method Reference; Constructor Method Reference The return type of both the method and the lambda function have to match. Changing the local variable may lead to some confusing behavior, as the programmer might  The method reference Person::compareByAge is semantically the same as the lambda expression (a, b) -> Person.compareByAge(a, b). Each has the following characteristics: Its formal parameter list is copied from Comparator<Person>.compare, which is (Person, Person). Its body calls the method Person.compareByAge.

Comments
  • See What is the equivalent lambda expression for System.out::println? and java.lang.NullPointerException is thrown using a method-reference but not a lambda expression