Tips
"Effective Java, third Edition" an English version has been published, the second edition of this book presumably many people have read, known as one of the four major Java books, but the second edition of 2009 published, to now nearly 8 years, but with Java 6, 7, 8, and even 9 of the release, the Java language has undergone profound changes.
In the first time here translated into Chinese version. For everyone to learn to share.
43. Method references are better than lambda expressions
The main advantage of lambda over anonymous classes is that it is more concise. Java provides a way to generate function objects, more concise than lambda, that is: Method references. Here is a snippet of program code that maintains a mapping from any key to an integer value. If the value is interpreted as the number of instances of the key, the program is an implementation of a multi-collection. The function of this code is to find an integer value based on the key, and then add 1 on that basis:
map.merge(key, 1, (count, incr) -> count + incr);
Note that this code uses the merge method, which has been added to the map interface in Java 8. If there is no mapping for the given key, the method simply inserts the given value; If the mapping already exists, the merged given function applies to the current value and the given value, and overwrites the current value with the result. This code represents a typical use case for the merge method.
The code is good to read, but there are still some boilerplate flavors. The parameters count and incr do not add too much value and take up considerable space. Really, all Lambda tells you that the function returns the two parameter's and. Starting with Java 8, the integer class (and all other wrapper numeric primitives) provides a static method sum, exactly as it is. We can simply pass a reference to this method and get the same result with less visual confusion:
map.merge(key, 1, Integer::sum);
The more parameters of the method, the more templates you can eliminate by means of the method reference. However, in some lambda, the selected parameter name provides a useful document that makes lambda more readable and maintainable than the method reference, even if the lambda looks longer.
There's nothing you can do about a method reference, because you can't do anything with lambda (there's only one hard-to-understand exception-if you're curious, see jls,9.9-2). In other words, a method reference usually results in shorter, clearer code. If the lambda becomes too long or too complex, they will give you a result: You can extract the code from the lambda into a new method and replace the lambda with a reference to the method. You can give this method a good name and record it in a document.
If you are programming with the IDE, it will provide a way to replace the lambda and use the method reference anywhere. Usually, you should accept the offer. Occasionally, Lambda is more concise than method references. This often happens in the same class as the lambda method. For example, consider this code, which is assumed to appear in a class named goshthisclassnameishumongous:
service.execute(GoshThisClassNameIsHumongous::action);
This lambda is similar to the code equivalent to the following:
service.execute(() -> action());
The code snippet referenced by the method is neither shorter nor clearer than the code fragment that uses lambda, so prefers the latter. In a similar line of code, the function interface provides a common static factory method to return the identity function Function.identity()
. It is usually shorter and cleaner, rather than using this method, and instead uses the equivalent lambda inline code: x - > x
.
Many method references refer to static methods, but there are four ways to do this. Two of these are specific (bound) and arbitrary (unbound) object method references. In a particular object reference, the receiving object is specified in the method reference. A particular object reference is inherently similar to a static reference: The function object has the same parameters as the referenced method. In any object reference, the receiving object is specified by an additional parameter before the method's declaration parameter when the function object is applied. Any object reference is typically used as a mapping and filtering method (entry 45) in the flow pipeline (pipelines). Finally, for classes and arrays, there are two ways to construct a method reference. Constructs a method reference to use as a factory object. The following table summarizes all of the five method references:
method Reference type |
example |
equivalent lambda |
Static |
integer::p arseint |
str-integer.parseint (str) |
Bound |
instant . Now ():: Isafter |
instant then = Instant.now (); t, Then.isafter (t) |
unbound |
string::tolowercase |
str-Str.tolowercase () |
class Constructor |
treemap :: New |
() new TreeMap |
Array Constructo R |
int[]::new |
len-new Int[len] |
In summary, method references typically provide a more concise choice for lambda. If the method references look shorter and clearer, use them, or stick to Lambda.
Effective Java Third Edition--43. Method reference is better than lambda expression