I have the following code:
final var fieldValuesStream = items.stream()
.map(person -> PersonFieldGetter.getFieldValueAsNumber(functionsParameters.getFieldName(), person)) // Number
.mapToDouble(number -> number.doubleValue());
IDEA highlights "number -> number.doubleValue()" with the message:
Lambda can be replaced with method reference
Replace Lamda with method reference
But when I change the code to .mapToDouble(Number::doubleValue)
a compile error happens:
QueryProcessor.java:31:34 java: incompatible types: invalid method reference method doubleValue in class java.lang.Number cannot be applied to given types required: no arguments found: java.lang.Object reason: actual and formal argument lists differ in length
Full source code
Why is this happening?
Project to reproduce the problem
EDIT: Added link to GitHub project with example project that is failing to build using:
IntelliJ IDEA 2021.2.3 (Ultimate Edition)
Build #IU-212.5457.46, built on October 12, 2021
Runtime version: 11.0.12+7-b1504.40 amd64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
SDK: Oracle OpenJDK 17.0.1
Method references are a special type of lambda expressions. They're often used to create simple lambda expressions by referencing existing methods. There are four kinds of method references: Static methods. Instance methods of particular objects.
The method references can only be used to replace a single method of the lambda expression. A code is more clear and short if one uses a lambda expression rather than using an anonymous class and one can use method reference rather than using a single function lambda expression to achieve the same.
Method reference is used to refer method of functional interface. It is compact and easy form of lambda expression. Each time when you are using lambda expression to just referring a method, you can replace your lambda expression with method reference.
To make the code clearer, you can turn that lambda expression into a method reference: Consumer<String> c = System. out::println; In a method reference, you place the object (or class) that contains the method before the :: operator and the name of the method after it without arguments.
In those cases, it looks clear to refer to the existing method by name. The method references can do this, they are compact, easy-to-read as compared to lambda expressions. A method reference is the shorthand syntax for a lambda expression that contains just one method call.
Java 8 Object Oriented Programming Programming Lambda expression is an anonymous method (method without a name) that has used to provide the inline implementation of a method defined by the functional interface while a method reference is similar to a lambda expression that refers a method without executing it.
A code is more clear and short if one uses a lambda expression rather than using an anonymous class and one can use method reference rather than using a single function lambda expression to achieve the same. In general, one doesn’t have to pass arguments to method references.
First, most method references do not need desugaring by the lambda metafactory, they are simply used as the reference method. Under the section "Lambda body sugaring" of the Translation of Lambda Expressions ("TLE") article:
import java.util.List;
public class Main {
public static void main(String[] args) {
List.of(0.1d).stream().map(aDouble -> {
return List.of(1).stream().map(p -> aDouble).mapToDouble(Number::doubleValue);
}
);
}
}
Seems the problem is the compiler can't recognize the type of aDouble
in the nested stream and cause some strange error.
Stream.of(0.1d).map(aDouble ->
List.of(1).stream().map(p -> aDouble).mapToDouble(Double::doubleValue)
);
aDouble
Stream.of(0.1d).map((Double aDouble) -> {
return List.of(1).stream().map(p -> aDouble).mapToDouble(Double::doubleValue);
}
);
Stream.of(0.1d).map(aDouble -> {
return List.of(1).stream().map(p -> aDouble).mapToDouble(d -> d.doubleValue());
}
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With