I read in a book (Fischer's Java Closures and Lambda, Apress 2015) that method references are preferable to lambda expressions. From my point of view, the lambda expression is more easily understandable to developers who use other languages. Then why does it say the method reference is preferable? Is writing a lambda expression a bad practice in Java 8?
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.
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.
Java supports lambda expressions but not the Closures. A lambda expression is an anonymous function and can be defined as a parameter. The Closures are like code fragments or code blocks that can be used without being a method or a class.
A lambda expression is a short block of code which takes in parameters and returns a value. Lambda expressions are similar to methods, but they do not need a name and they can be implemented right in the body of a method.
In the Lambda Best Practices section of Chapter 2, Fischer's book says:
As much as possible, use a method reference instead of a lambda. Method references are not only shorter and easier to read, but using method references will get you thinking directly about the methods as values. This is the code you need to excise from your codebase and your brain:
x -> it.do(x)
If you are naturally writing that code, then you still have not made the leap to thinking at the higher level of functional programming. Once you make that leap, it will become much easier to communicate and work with complex functions, because you will be thinking in types, not in values.
Although I mostly agree with the conclusion, I'm not sure I buy Fischer's line of reasoning. Method references are often, though not always, shorter than the written-out lambda. In the first part he says that method references will help you think about methods as values. OK, but then later he says things will become easier because you'll be thinking in types, not values. I'm not sure what that means.
It's possible to rewrite the example expression he gives as
it::do
That's certainly shorter than the original, but it's hard to generalize from a tiny example.
Here's my take on method references vs. written-out lambdas.
If there is a choice between using a lambda expression and a method reference, it is often the case that a method reference is preferable. But this is not a hard-and-fast rule, and there are likely to be circumstances where a lambda expression is preferable. It's also somewhat a matter of taste.
If you're familiar with lambda expressions from other languages, then lambda expressions in Java will probably be more immediately familiar than method references. However, I believe this to be a temporary state until you learn method references. Once they're more familiar, the advantages of method references can outweigh the initial unfamiliarity.
Consider this simple example of getting the lengths of strings:
List<String> list = ... ;
int[] lengths1 = list.stream().mapToInt(s -> s.length()).toArray();
int[] lengths2 = list.stream().mapToInt(String::length).toArray();
In this case, the size of the lambda expression is just about the same as the size of the method reference (in the number of characters). But notice that the method reference contains more type information. It tells the reader that the element type is String
, which may be helpful in understanding a long pipeline. It is sometimes also helpful to the compiler, if it cannot infer the element type, as sometimes occurs in complex expressions.
Another point is that, using a method reference will often relieve you of the responsibility of coming up with a name for a formal parameter that's simply passed to another method. Naming is often important, but lambda formals are often "garbage" names like i
x
or s
as in this example.
The method reference is a tiny bit more efficient, as it doesn't need to generate a static method that must be called through to get to the String.length() method. But this efficiency is rarely an important consideration.
Consider also this example, deliberately stripped of context:
(x, y) -> x + y
Is this string concatenation or numeric addition? If numeric, what type? Under the rules of the language, this must be known at compile time, otherwise it's an error. Although it might be clear to the compiler, sometimes this isn't very clear to the reader. Consider instead these method references:
String::concat
Integer::sum
Double::sum
Using a name for the operation in this case makes it very explicit to the reader about what is intended.
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