Chine _java using lambda expressions in Java programming

Source: Internet
Author: User
Tags anonymous variable scope

Why use lambda expressions
let's look at a few examples:

The first example is to perform a task in a separate thread, as we usually do:

Class Worker implements Runnable {public
  void run () {for
    (int i = 0; i < i++)
      doWork ();
  }
  . ..
}

Worker W = new Worker ();
New Thread (W). Start ();

The second example, the custom string comparison method (through the string length), generally does this:

Class Lengthcomparator implements comparator<string> {public
  int compare (string A, string second) { Return
    Integer.compare (First.length (), second.length ());
  }
Arrays.sort (Strings, New Lengthcomparator ());

The third example, in JavaFX, adds a callback to a button:

Button.setonaction (New eventhandler<actionevent> () {public
  void handle (ActionEvent event) {
    System.out.println ("for clicking!");
  }
);

These examples have one thing in common: Define a block of code first, pass it to an object or method, and then execute it. In the lambda table
Java is not allowed to pass code blocks directly, because Java is object-oriented, so you have to pass an object that will
The code block that is executed is encapsulated in the object.

Syntax for lambda expressions
the Lengthcomparator in the second example above is represented by a lambda expression as:

(String A, string second)-> Integer.compare (First.length (), 
  second.length ());

The-> is a list of parameters, followed by an expression statement body;

If the expression statement body is more than one row, the statement body is written in {}, just like a normal function:

(String A, string second)-> {
  if (first.length () > Second.length ()) {return
    1;
  } else if (first.le Ngth () = = Second.length ()) {return
    0;
  } else {
    return-1
  ;
}};

If there are no parameters, () or need to take, for example, the first example above, can be expressed as:

()-> {for
  (int i = 0; i < 1000 i + +) {
    doWork ();
  }
}

If the type of the parameter can be inferred automatically from the context, you can omit:

Comparator<string> Comp
  = (i, second)//Same as (string A, string second)
  -> Integer.compare (fi Rst.length (), second.length ());

If there is only one argument and the type can be inferred automatically, the parentheses () can also be omitted:

Instead of (event)-> or (ActionEvent event)->
eventhandler<actionevent> listener = 
  Event-> Sy Stem.out.println ("for clicking!");

The type of the return value of a lambda expression is automatically inferred, so it is not necessary to indicate; in a lambda expression, some conditional branches
Returns a value, and the other branches do not return a value and are not allowed, such as:

(x)-> {
  if (x >= 0) {return
    1;
  }
}

In addition, the difference between the expression lambda and the statement lambda is that the expression lambda does not need
Write return keyword, the Java runtime returns the result of the expression as return value, and statement lambda is
Expressions written in {} need to use the return keyword, for example:

Expression lambda
comparator<string> comp1 = 
  (i, second)-> Integer.compare (First.length (), Second.length ());

Statement lambda
comparator<string> comp2 = (i, second)-> 
  {return Integer.compare ( First.length (), second.length ());

Functional Interface
if an interface (interface) has only one abstract method (abstract methods), it is called
Functional Interface, such as runnable, comparator and so on.
You can use lambda expressions in any place where you need to functional interface objects:

Arrays.sort (words, 
  (second)-> Integer.compare (First.length (), second.length ());

Here, the second parameter of sort () requires a comparator object, and comparator is
Functional Interface, so you can pass in a lambda expression directly, calling the Compare () method of the object
, is the execution of the statement body in the lambda expression;

If the statement of the lambda expression realizes that an exception is thrown, the abstract method in the corresponding functional interface must be thrown
Out of this exception, you need to explicitly catch an exception in a lambda expression:

Runnable r = ()-> {
  System.out.println ("------");
  try {
    thread.sleep;
  } catch (Interruptedexception e) {
    //catch Exception
  }
};

callable<string> C = ()-> {
  System.out.println ("--------");
  Thread.Sleep (ten);
  Return "";
};

Method Reference
if the parameters of a lambda expression are passed as arguments to a method whose execution effect is the same, the lambda expression
You can use method reference expression, which is equivalent in the following two ways:

(x)-> System.out.println (x)
System.out::p rintln

where System.out::p rintln is called method Reference.

There are three main forms of method reference:

    • Object::instancemethod
    • Class::staticmethod
    • Class::instancemethod

For the first two ways, the corresponding lambda expression parameters are consistent with the parameters of method, such as:

System.out::p rintln
(x)-> System.out.println (x)

Math::p ow (x 
, y)-> Math.pow (x, y)

For the third Way, the corresponding lambda expression in the statement body, the first argument as an object, call method, the other parameters
As a parameter of method, such as:

String::comparetoignorecase
(S1, S2)-> s1.comparetoignorecase (S2), 1.5 constructor Reference

Constructor reference is similar to method reference, but is a special method:new, which constructor is specifically invoked, determined by the context environment, such as:

list<string> labels = ...;
stream<button> stream = Labels.stream (). Map (button::new);

Button::new is equivalent to (x)-> button (x), so the constructor called is: button (x);

In addition to creating a single object, you can create an array of objects, equivalent to the following two ways:

Int[]::new 
(x)-> new Int[x]

Variable scope
The LAMBD expression captures the variables available under the current scope, such as:

public void Repeatmessage (String text, int count) {
  Runnable r = ()-> {for
    (int i = 0; I < count i + +) { C3/>system.out.println (text);
      Thread.yield ();
    }
  ;
  New Thread (R). Start ();

But these variables must be immutable, why? Look at the following example:

int matches = 0;
for (Path p:files)
  new Thread (()-> {if (P has some) matches++;}). Start (); 
  Illegal to mutate matches

Because mutable variables are not thread-safe in lambda expressions, this is consistent with the requirements of the inner class, which can only be referenced in the inner class
An externally defined final variable;

The scope of a lambda expression is the same as the scope of the nested code block, so the parameter name or variable name in the LAMBD expression does not
Can conflict with local variables, such as:

Path-i = Paths.get ("/usr/bin");
Comparator<string> comp = (second)-> Integer.compare (First.length (),
   second.length ());//Error: Variable-Already defined

If you refer to the this variable in a lambda expression, you are referring to the this variable of the method that created the lambda expression, such as:

public class application () {public
  void DoWork () {
    Runnable runner = ()-> {
      ...;
      System.out.println (This.tostring ());
      ...
    };
  }
}

So here's this.tostring () calls the Application object's toString (), not the runnable
object's.


Default method
there can only be abstract methods in an interface, and if a method is added to an existing interface, all implementation classes of that interface need to implement the method.
The concept of default method is introduced in Java 8 to add a default in an interface that does not break an existing
Port rule, the implementation class of an interface can optionally override or directly inherit the default method, for example:

Interface Person {
  long getId ();
  Default String getName () {return ' John Q. Public ';}
}

Java is allowed for multiple inheritance if the method defined in the parent class of a class is identical to the default method defined in the interface, or
How do you handle this conflict when the exact same method is defined in the two interfaces of a class? The processing rules are as follows:

If the method of the parent class and the interface conflicts: The method in the parent class is the same, the methods in the interface are ignored;
If the default method in two interfaces conflicts, you need to override the method to resolve the conflict;

Static method
Java 8, before the interface can be defined only static variables, Java 8 Start, the interface can add static methods, such as
The comparator interface adds a series of comparingxxx static methods, such as:

public static <T> comparator<t> Comparingint (tointfunction< super t> 
  keyextractor) {
  Objects.requirenonnull (keyextractor);
  Return (comparator<t> & Serializable)
   (c1, C2)-> Integer.compare (Keyextractor.applyasint (C1), 
       Keyextractor.applyasint (C2));

With this static method, the following two ways are also equivalent:

1,

Arrays.sort (cities, (second)-> Integer.compare (First.length (), 
  second.length ());

2,

Arrays.sort (Cities, Comparator.comparingint (String::length));

So, in the future, when we design our own interfaces, we do not need to define separate tool classes (such as Collections/collection),
It's OK to use the static method in the interface.

Anonymous inner class

In the Java world, anonymous inner classes can implement actions that may be performed only once in an application. For example, in an Android application, a button's click event is handled. You don't have to write a separate class to handle a click event, you can do it with an anonymous inner class:

Button button = (button) Findviewbyid (r.id.button1);
Button.setonclicklistener (New Onclicklistener () {
 
  @Override public
  void OnClick (view view) {
    Toast.maketext (mainactivity.this, "button clicked", Toast.length_short). Show ();
 

LAMBDA Example
1.Runnable Lambda
To see a few examples, here is an example of a Runnable:
 public void Runnabletest () {System.out.println ("= = = Runnabletest = ="); An anonymous Runnable Runnable r1 = new Runnable () {@Override public void run () {System.out.print
      ln ("Hello World one!");
    }
    };
    Lambda Runnable Runnable r2 = ()-> System.out.println ("Hello World two!");
    Executes two run functions R1.run ();
  R2.run (); 
 public void Runnabletest () {System.out.println ("= = = Runnabletest = ="
    ); An anonymous Runnable Runnable r1 = new Runnable () {@Override public void run () {System.out.println (
      "Hello World one!");
 
    }
    };
 
    Lambda Runnable Runnable r2 = ()-> System.out.println ("Hello World two!");
    Executes two run functions R1.run ();
  R2.run (); }
Both implementations have no parameters and no return value. Runnable lambda expressions use code blocks to simplify the five-element code into a single statement.
2. Comparator Lambda
In Java, the Comparator interface is used to sort collections. In the following example, a ArrayList contains some person objects and sorts them according to the surName of the person object. The following are the fields contained in the person class:
public class Person {
  private String givenname;
  Private String surName;
  private int age;
  Private Gender Gender;
  Private String EMail;
  Private String phone;
  Private String address;

public class Person {
  private String givenname;
  Private String surName;
  private int age;
  Private Gender Gender;
  Private String EMail;
  Private String phone;
  Private String address;

The following are the ways to implement the Comparator interface individually with anonymous inner classes and LAMBDA expressions:
 public class Comparatortest {public static void main (string[] args) {List<per
    son> personlist = Person.createshortlist (); Use the Inner class implementation sort Collections.sort (Personlist, New comparator<person> () {public int compare (person P1, person
      P2) {return p1.getsurname (). CompareTo (P2.getsurname ());
    }
    });
    System.out.println ("= = = Sorted Asc SurName = = =");
    for (person p:personlist) {p.printname ();
    ///ascending order of System.out.println ("= = Sorted Asc SurName = = =") using LAMBDA expressions;
    Collections.sort (personlist, person P1, person p2)-> p1.getsurname (). CompareTo (P2.getsurname ()));
    for (person p:personlist) {p.printname ();
    }//descending order System.out.println ("= = = Sorted Desc SurName = =");
    Collections.sort (Personlist, (P1, p2)-> p2.getsurname (). CompareTo (P1.getsurname ()));
    for (person p:personlist) {p.printname (); }
  }
}
 public class Comparatortest {public static void main (string[] args) {list<person>
 
    Personlist = Person.createshortlist (); Use the Inner class implementation sort Collections.sort (Personlist, New comparator<person> () {public int compare (person P1, person
      P2) {return p1.getsurname (). CompareTo (P2.getsurname ());
 
    }
    });
    System.out.println ("= = = Sorted Asc SurName = = =");
    for (person p:personlist) {p.printname ();
    ///ascending order of System.out.println ("= = Sorted Asc SurName = = =") using LAMBDA expressions;
    Collections.sort (personlist, person P1, person p2)-> p1.getsurname (). CompareTo (P2.getsurname ()));
    for (person p:personlist) {p.printname ();
    }//descending order System.out.println ("= = = Sorted Desc SurName = =");
    Collections.sort (Personlist, (P1, p2)-> p2.getsurname (). CompareTo (P1.getsurname ()));
    for (person p:personlist) {p.printname (); }
  }
}
You can see that an anonymous inner class can be implemented through a LAMBDA expression. Note that the first lambda expression defines the type of the parameter as person, and the second lambda expression omits the type definition. LAMBDA expressions support types that can be omitted if the desired type is pushed out through the context. Here, because we use LAMBDA expressions in a Comparator place that uses generic definitions, the compiler can pull out the two parameter types as person.

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.