Java Lambda expressions and sample code _java

Source: Internet
Author: User
Tags anonymous instance method

Java LAMBDA expressions are a new feature introduced in Java 8, a syntactic candy that simulates functional programming, similar to a closure in Javascript, but somewhat different, primarily to provide a functional syntax to simplify our coding.

LAMBDA Basic Syntax

The basic structure of the LAMBDA is (arguments)-> body, there are several situations:

    1. When a parameter type is inferred, no type needs to be specified, such as (a)-> System.out.println (a)
    2. When there is only one argument and the type can be inferred, do not force write (), such as a-> System.out.println (a)
    3. Parameter must have parentheses when specifying a type, such as (int a)-> System.out.println (a)
    4. Parameter can be empty, such as ()-> System.out.println ("Hello")

The body needs to contain the statement with {}, when only one statement {} can be omitted

The common wording is as follows:

(a)-> a * a
(int a, int b)-> A + b
(A, B)-> {return a-b;}
()-> System.out.println (Thread.CurrentThread (). GetId ())

Function-type interface Functionalinterface

Concept

Java Lambda expressions are based on functional interfaces. What is a functional interface (Functionalinterface)? In short, there is only one method (function) interface, which is intended for a single operation and is equivalent to a single function. Common interfaces such as: Runnable, Comparator are functional interfaces, and all annotations are annotated @FunctionalInterface.

Example

Taking Thread as an example shows that it's easy to understand. The Runnable interface is a common interface for threading programming, and contains a method void run (), which is the logic of the thread's operation. In the previous syntax, our new thread typically uses the Runnable anonymous class, as follows:

New Thread (New Runnable () {
  @Override public
  void Run () {
    System.out.println thread.currentthread (). GetId ());

Start ();

If it's too much to write, it's boring, and the Lambda-based writing becomes simple and straightforward, as follows:

New Thread (()-> System.out.println (Thread.CurrentThread (). GetId ())). Start ();

Note the parameters of the Thread, Runnable Anonymous implementation is achieved by a sentence, written below to better understand

Runnable r = ()-> System.out.println (Thread.CurrentThread (). GetId ());
New Thread (R). Start ();

Of course, the purpose of LAMBDA is not only to write concise, a higher level of purpose and so on to conclude.

Look at an example of a comparator, according to the traditional wording, as follows:

Integer[] A = {1, 8, 3, 9, 2, 0, 5};
Arrays.sort (A, new comparator<integer> () {
  @Override public
  int compare (integer o1, integer o2) {
    return o1-o2;
  }
});

The LAMBDA expression is written as follows:

Integer[] A = {1, 8, 3, 9, 2, 0, 5};
Arrays.sort (A, (O1, O2)-> O1-o2);

Functional interfaces in the JDK

For existing class libraries to be able to use LAMBDA expressions directly, some of the previous interfaces of Java 8 have been labeled as functional interfaces:

    1. Java.lang.Runnable
    2. Java.util.Comparator
    3. Java.util.concurrent.Callable
    4. Java.io.FileFilter
    5. Java.security.PrivilegedAction
    6. Java.beans.PropertyChangeListener

Java 8 is a new addition to the package java.util.function, bringing the common functional interface:

    1. function<t, r>-function: input t output r
    2. bifunction<t, U, r>-function: input t and U output R object
    3. Predi Cate<t>-assertion/judgment: input T output boolean
    4. bipredicate<t, u>-assertion/judgment: input T and U output Boolean
    5. SUPPLIER&L T T>-Producer: no input, output T
    6. consumer<t>-Consumer: input T, no output
    7. biconsumer<t, u>-Consumer: input T and U no output
    8. unaryoperator<t>-cell operation: input t output t
    9. binaryoperator<t>-Two-dollar operation: input T and t output T

In addition, more specific functions are added to the basic type of processing, including: Booleansupplier, Doublebinaryoperator, Doubleconsumer, Doublefunction<r> Doublepredicate, Doublesupplier, Doubletointfunction, Doubletolongfunction, Doubleunaryoperator, IntBinaryOperator, Intconsumer, Intfunction<r>, Intpredicate, Intsupplier, Inttodoublefunction, Inttolongfunction, Intunaryoperator, Longbinaryoperator, Longconsumer,longfunction<r>, Longpredicate, LongSupplier, Longtodoublefunction,longtointfunction, Longunaryoperator, Todoublebifunction<t, U>, ToDoubleFunction<T >,tointbifunction<t, U>, Tointfunction<t>, Tolongbifunction<t, U>, ToLongFunction<T>. With the above functional interface, the function interface of these basic types can see the function of the interface through the class name.

To create a functional interface

Sometimes we need to implement a functional interface, the practice is very simple, first of all you have to ensure that this interface can only have a function operation, and then on the interface type annotation @FunctionalInterface can be.

Type inference

Type inference is the basis of lambda expressions, and the process of type derivation is the compilation of lambda expressions. Take the following code as an example:

function<string, integer> strtoint = str-> integer.parseint (str);
During compilation, I understand the process of type derivation as follows:

    1. Determine the target type Function first
    2. function as a functional interface whose method signature is: Integer apply (String t)
    3. Detect if str-> integer.parseint (str) matches the method signature (parameter type, number, order, and return value type of the method)
    4. If it does not match, a compile error is reported

The target type here is the key, gets the method signature through the target type, and then contrasts with the LAMBDA expression.

Method reference

The basis of a method reference (methods Reference) is also a functional interface, which can be implemented directly as a function interface, and has the same effect as a LAMBDA expression, and also relies on type inference. A method reference can be considered a simplification of a LAMBDA expression that invokes only one method.

The syntax for the method reference is: Type::methodname or Instancename::methodname, and the constructor corresponds to the MethodName for new.

For example, the above examples were used:

function<string, integer> strtoint = str-> integer.parseint (str);

The corresponding method reference is written as

function<string, integer> strtoint = Integer::p arseint;

Depending on the type of method, the method reference is mainly divided into several types, such as constructor reference, static method reference, instance method reference on instance, instance method reference on type, etc.

To construct a method reference

The syntax is: type::new. Like the following function to convert a string to an array

Method reference notation

function<string, integer> strtoint = integer::new;

Lambda notation

function<string, integer> strtoint = str-> new Integer (str);

Traditional wording

function<string, integer> strtoint = new function<string, integer> () {
  @Override public
  Integer Apply (String str) {return
    new Integer (str);
  }
;


Array constructor Method reference

The syntax is: type[]::new. As in the following function to construct a string array of a specified length

Method reference notation

Function<integer, string[]> fixedarray = string[]::new;

Method reference notation

Function<integer, string[]> fixedarray = length-> new string[length];

Traditional wording

Function<integer, string[]> fixedarray = new Function<integer, string[]> () {
  @Override
  public String[] Apply (Integer length) {return
    new string[length];
  }
;

static method Reference

The syntax is: type::new. As in the following function to convert a string to an array

Method reference notation

function<string, integer> strtoint = Integer::p arseint;

Lambda notation

function<string, integer> strtoint = str-> integer.parseint (str);

Traditional wording

function<string, integer> strtoint = new function<string, integer> () {
  @Override public
  Integer Apply (String str) {return
    integer.parseint (str);
  }
;

instance method reference on instance

The syntax is: Instancename::methodname. The following judgment function is used to determine whether a given name exists in the list

list<string> names = arrays.aslist (new string[]{"John", "Dick", "Harry"});
predicate<string> checknameexists = names::contains;
System.out.println (Checknameexists.test ("John"));
System.out.println (checknameexists.test ("Zhang Si"));

instance method reference on type

The syntax is: Type::methodname. A run-time reference is an object in the context, such as the following function to return the length of a string

function<string, integer> calcstrlength = string::length;
System.out.println (Calcstrlength.apply ("John"));
list<string> names = arrays.aslist (new string[]{"Zhangsan", "Lisi", "Wangwu"});
Names.stream (). Map (String::length). ForEach (System.out::p rintln);

For example, the following function has specified a delimiter split string as an array

Bifunction<string, String, string[]> split = String::split;
string[] names = split.apply ("Zhangsan,lisi,wangwu", ",");
System.out.println (arrays.tostring (names));

Stream Object

Concept

What is Stream? The stream here differs from the IO InputStream and Outputstream,stream in the package Java.util.stream, which is also a new Java 8 addition, stream is a set of elements that support serial parallel aggregation operations, and can Understood as an enhanced version of a collection or iterator. What is an aggregation operation? Simple examples of common averages, maximum, minimum, sum, sorting, filtering, and so on.

Several characteristics of the Stream:

Single processing. At the end of the process, the current stream is closed.
Support for parallel operations
Common way to get the Stream

Gets from the collection

Collection.stream ();
Collection.parallelstream ();

Static Factory

Arrays.stream (Array)
Stream.of (T ...)
Intstream.range ()
Here is a simple introduction to the Stream, the following will have specific applications. There is nothing particularly close to the relationship between the stream and the lambda expression, but the lambda expression greatly facilitates the use of the stream. If there is no LAMBDA expression, the use of the Stream will produce a large number of anonymous classes, very awkward.

Example

The following demo relies on the employee object and the List object made up of the employee object.

 public class Employee {private String name;
  Private String sex;

  private int age;
    Public Employee (string name, string sex, int age) {super ();
    THIS.name = name;
    This.sex = sex;
  This.age = age;
  Public String GetName () {return name;
  Public String Getsex () {return sex;
  public int getage () {return age;
    @Override public String toString () {StringBuilder builder = new StringBuilder (); Builder.append ("Employee {name="). Append (name). Append (", sex="). Append (Sex). Append (", age="). Append (age). Append ("
    }");
  return builder.tostring ();
} list<employee> Employees = new arraylist<> ();
Employees.add (New Employee ("John", "Male", 25));
Employees.add (New Employee ("Dick", "female", 24));
Employees.add (New Employee ("Harry", "female", 23));
Employees.add (New Employee ("Saturday", "male", 22));
Employees.add (New Employee ("Sun Seven", "female", 21));

Employees.add (New Employee ("Liu Eight", "male", 20)); 

Print all employees

Collection provides a ForEach method for us to manipulate individual objects individually.

Employees.foreach (e-> System.out.println (e));
Or
Employees.stream (). ForEach (e-> System.out.println (e));

Sort by age

Collections.sort (Employees, (E1, E2)-> e1.getage ()-e2.getage ());
Employees.foreach (e-> System.out.println (e));
Or
Employees.stream (). Sorted (E1, E2)-> e1.getage ()-e2.getage ()). ForEach (e-> System.out.println (e));
Print the oldest female employee

Max/min returns the largest/smallest element under the specified sort condition

Employee Maxagefemaleemployee = Employees.stream ()
    . Filter (E-> "female". Equals (E.getsex ())
    . Max (E1, E2)- > E1.getage ()-e2.getage ())
    . get ();
System.out.println (Maxagefemaleemployee);

Print out male employees older than 20

Filter filters out elements that meet the criteria

Employees.stream ()
. Filter (e-> e.getage () > && "Male". Equals (E.getsex ()))
. ForEach (e-> System.out.println (e));
Print out the oldest 2 male employees

Limit method intercepts a finite element

Employees.stream ()
    . Filter (E-> "man". Equals (E.getsex ()))
    . Sorted (e1, E2)-> e2.getage ()-e1.getage ())
    . Limit (2)
    . ForEach (E-> System.out.println (e));

Print out the names, use, and separation of all male employees

Map composes the new stream with the returned value of the function given by the execution of all elements in the stream

String maleemployeesnames = Employees.stream ()
    . Map (e-> e.getname ())
    . Collect (Collectors.joining (","));
System.out.println (Maleemployeesnames);

Statistical information

Intsummarystatistics, Doublesummarystatistics, Longsummarystatistics contains the summarized data in the Stream.

Intsummarystatistics stat = Employees.stream ()
    . Maptoint (Employee::getage). Summarystatistics ();
SYSTEM.OUT.PRINTLN ("Total staff:" + stat.getcount ());
System.out.println ("The highest Age:" + Stat.getmax ());
System.out.println ("Minimum Age:" + stat.getmin ());
System.out.println ("average age:" + stat.getaverage ());

Summarize

Lambda expressions can really reduce a lot of code, can improve productivity, and of course, there are drawbacks, is the complexity of the expression is less readable, it may be not very accustomed to the sake of it, if accustomed to, I believe will like. Everything has two sides, it depends on how we balance the pros and cons, especially in a team.

The above is the JAVA8 JAVALAMBDA data collation, follow-up continue to supplement the relevant information thank you for your support of this site!

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.