Java 8 lambdas Depth study

Source: Internet
Author: User

Blog Address http://colobu.com


Java 8 released for a while, it was possible to focus on the lambda in Java 8 earlier and to be familiar with the most important language changes in Java 8. This article will delve into the lambda features in Java 8 and the stream interface to discuss some deep technical details.
For example, a lambda expression that serializes a reference to a captured context variable after deserialization. The lambda expression is recursive. The difference between a reference to a class method and a reference to an instance method. Problem with Diamond inheritance. The lazy and eager modes of the stream interface. The performance of the lambda.

Java Lambda syntax

Although you are already familiar with it, let's review the syntax of the lambda expression first.

"A lambda expression is a method:it provides a list of formal parameters and a Body-an expression or block-expressed In terms of those parameters, "
JSR 335

1
Function<integer, integer> fun = (integer x, integer y), {return x + y;}

If the body has only one expression, you can omit the body's curly braces and return .

1
Function<integer, integer> fun = (integer x, integer y), x + y

Parameters can declare types, or they can be omitted based on type inference.

1
Function<integer, integer> fun = (x, y) x + y

But not partially omitted.

1
Wrong

A single argument can omit parentheses.

12
Function<integer, integer> fun = (x)-x+1function<integer, integer> fun = x-x+1

However, you cannot add a type declaration.

1
Function<integer, integer> fun = Integer x, x+1//wrong

If there are no arguments, the parentheses are required.

12
1995 (), {System.GC ();}
Java Lambda recursion

An anonymous function does not have a name, but a lambda expression can be assigned to a variable or passed as a parameter, which means it has a "name." So can you use this name for recursion?
Lambdafaq website said yes.

12
Function<long, long> fib = x, {if (x = =12return1Else return fib.apply (x-1) + x;}; System.out.println (Fib.apply (3L));

You can't actually compile this code because the compiler thinks the fib might not be initialized.

1
The local variable fib may not be been initialized

Is there any way to pass the recursion?
There are some hacked methods, such as

12
null }; foo[0return  0)?  1: x* foo[0].applyasdouble (x1);};

or (the creation of a generic array is a little cumbersome)

1234567891011121314
   @SuppressWarnings("Unchecked")Private Static<E> e[]NewArray(Class Clazz,intSize) {return(e[])  Array.newinstance (clazz, size); } Public Static void Main(string[] args)throwsInstantiationexception, Illegalaccessexception, SecurityException, nosuchmethodexception {//function<long, long> fib = x, {if (x ==1 | | x = = 2) return 1L; else return fib.apply (x-1) + x;};Function<long, long>[] funs = NewArray (Function.class,1); funs[0] = x, {if(x = =1|| x = =2)return 1LElse returnfuns[0].apply (X-1) + x;}; System.out.println (funs[0].apply (TenL));}

Or use a helper class.

12
Bifunction<bifunction, Long, long> facthelper = (f, x), {if (x = =12return 1 Else return x + (long) f.apply (f,x-1);}; Function<long, long> fib = x, facthelper.apply (Facthelper, x);
Capturing variables

Just like local classes and anonymous classes, lambda expressions can capture variables (capture variable).

In addition, a local class had access to local variables. However, a local class can only access local variables is declared final. When a local class accesses a local variable or parameter of the enclosing block, it captures that variable or parameter

But a lambda expression does not force you to declare a variable as final, as long as it behaves as if it were the final variable, which is equivalent to final.
The following example does s not have to be declared final, and the actual plus final does not compile an error.

123
"Smallnest"; Runnable r = ()-System.out.println ("Hello" + s); R.run ();

But the following example is s not final, and the compilation will be wrong. ,

1234
"Smallnest"; Runnable r = ()-System.out.println ("Hello""Colobu"; R.run ();

The following code will also compile unsuccessfully:

123
"Smallnest" "abc"; System.out.println ("Hello" + s);}; R.run ();

Note that final is simply a variable that cannot be assigned, and the value of the variable field can be changed.

12345
New Sample (); S.setstr ("smallnest"); Runnable r = ()-System.out.println ("Hello" + s.getstr ()) S.setstr ("Colobu"); R.run ();

Here we can change the value of the Str field of S.

Serialization of general serialization/deserialization

Lambda expressions can be serialized. The following is a simple example.

12345678910
Runnable r = (Runnable & Serializable) (), System.out.println ("Hello serialization"new FileOutputStream ("runnable.lambda"newnew FileInputStream ("Runnable.lambda" New ObjectInputStream (FIS); r = (Runnable) is.readobject (); R.run ();

Note (Runnable & Serializable) is the new syntax in Java 8. Cast an object to a intersection of types by adding multiple bounds.
Whether a lambda can be serialized, the parameters it captures, and whether the target type can be serialized. Of course, the use of serialization in practice is discouraged. The above example R implements the serializable interface, and there is no captured argument, so it can be serialized.

Serialization/serialization with capture variables

Let's look at an example with captured argument.

12345678910111213141516171819202122232425262728
Class Sample implements Serializable {PrivateString str; PublicStringGetstr() {returnSTR;} Public void Setstr(String str) { This. str = str;}} Public Static void Serializelambda()throwsException {Sample s =NewSample (); S.setstr ("Smallnest"); Sampleserializableinterface r = ()-System.out.println ("Hello"+ S.GETSTR ()); FileOutputStream fos =NewFileOutputStream ("Runnable.lambda"); ObjectOutputStream OS =NewObjectOutputStream (FOS); Os.writeobject (R); S.setstr ("Colobu");} Public Static void Deserializelambda()throwsException {FileInputStream FIS =NewFileInputStream ("Runnable.lambda"); ObjectInputStream is =NewObjectInputStream (FIS); Sampleserializableinterface r = (sampleserializableinterface) is.readobject (); R.run ();}

You can see that it is serialized with captured argument together s . Even if it is deserialized, captured argument is not the same s .
The resulting output hello smallnest .

Method reference

A method reference is an interesting feature that can be directly referenced by a method like a pointer. New operator "::" method used to refer to a class or instance.

static method Reference
1234
Ten  One L System.out.println (Bf.apply (A, b));
Instance method reference
12
consumer<string> C = system.out::p rintln;c.accept ("Hello Colobu");

The method signature referenced in both cases is the same as the method signature of target type, and the method name is not necessarily the same.

Arbitrary instance Reference
12
"Barbara" "James" "Mary" "John" "Patricia" "Robert" "Michael" "Linda" }; Arrays.sort (Stringarray, string::comparetoignorecase);

This is a very interesting way to use. You can refer to an instance of any one type. The parameter list for the equivalent lambda expression is (string a, string b), and the method reference calls A.comparetoignorecase (b).

Constructor reference

Another special method reference is a reference to a constructor.
A reference to a constructor is similar to a reference to a static method, except that the method name is new . A class has more than one constructor, and the most appropriate constructor is chosen based on the target type.

Multiple inheritance

Because Java 8 introduces the attributes of the default method, Java also wants to encounter multiple inheritance problems in other languages like C + +. Here is a list of two typical multi-inheritance cases.

Triangular inheritance

The triangle inherits as shown.
A
|\
| \
| B
| /
C

12345678910
Class A {publica () {System.out.println ("A ()");}  Public A (int x) {System.out.println ("A (int x)");}}
12
New //b says
Diamond Inheritance

Diamond Inheritance as shown
A
/\
/ \
B C
\ /
D

1234567891011121314151617181920212223
Interface A {  defaultvoid say () {System.out.println ("A says");}} Interface B extends a{  defaultvoid say () {System.out.println ("B says");}} Interface C extends a{  defaultvoid say () {System.out.println ("C says");}} Class D implements A, B, c{  }

Error in direct compilation. The reason is duplicate default methods.
You need to D overload say methods in, customize, or use the parent class/interface method. Pay attention to the wording接口.super.default_method_name

12345
Class D implements A, B, c{publicvoidsay() {B.super. Say ();}}
Fork Type Inheritance

Fork type Inheritance as shown

B C
\ /
D

12345678910111213141516
Interface B {  defaultvoid say () {System.out.println ("b says");}} Class C {public  voidsay() {System.out.println ("C says");}} Class D extends C implements  b{  }

The above code output C says .

Principle:
Basically, you can judge the implementation rules for multiple inheritance according to the following three principles.

    1. The class takes precedence over the interface. If a subclass inherits a parent class and the interface has the same method implementation. Then the definition in the interface is ignored. As a third example.
    2. Methods in subtypes take precedence over methods in the province type. As a first example.
    3. If none of the above conditions are satisfied, as in the second example, you must show overwrite/implement its method, or declare it as abstract.
Stream interface. lazyMethods and eagerMethod

There are many ways to add a new stream interface.

lazyExample:

1
);

Filter does not immediately iterate through the list, it simply adds some "recipes" to the stream. Currently its method implementation will not be executed. It will not execute until a method of type eager is encountered.

eagerExample:

1
). Count ();

Principle:
Look at the return value of the method. If the stream object is returned, then it is lazy, and if another type or void is returned, it is eager and will be executed immediately.

Functional interface can only have one method?

Functional Interface is also known as single Abstract Method (SAM) or role Interface.
Can you declare only one method in the interface?
The above example also shows that you can define multiple default method in functional interface. In fact java.util.function many functional interface define the default method.
So, functional interface can declare multiple methods, except the default method? Look at an example.

12345
Interface MyI {void apply (int i); String toString ();}

Myi declares two methods of apply and ToString (). Can it be used as the target type of a lambda expression?

12
MyI m = x-System.out.println (x); M.apply (ten);

No problem, the code can be compiled properly, the program is running properly.
But, wait, not functional interface can only declare an abstract method?
In fact, you see the second method is very special, it is the same as the method signature of object. It is a method of implicit implementation of an object, so it can be ignored.

Again, interface Foo { boolean equals(Object obj); } it is not a functional interface because there is no declaration of a method.
"' Java
Interface Foo {
int m ();
Object Clone ();
}
Nor is it a functional interface, because Object.clone is not of the public type.

Performance of Lambda

Oracle's performance engineer Sergey Kuksenko has a good performance comparison document: JDK 8:LAMBDA Performance Study, a detailed and comprehensive comparison of performance differences between LAMBDA expressions and anonymous functions. Here is the video. On page 16, the worst (capture) is the same as inner class, Non-capture is 5 times times better than inner class.

The Lambda Development Group also has a PPT, which also describes the performance of lambda, including capture and non-capture scenarios. It looks like the worst case of lambda performance internal classes is better.

Java 8 Lambdas-they is fast, very fast also has an article (which may need to flip the wall), indicating that the lambda expression is also as fast.
Java 8 Lambda Performance Comparison


Java 8 lambdas Depth study

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.