Le byte -Java8 core features real -Lambda expression

Lambda expressions Java8 introduced, allowing developers to function as an argument passed to a method, or the code itself is processed as data. Use Lambda expressions, makes the application simple and compact. Many languages ​​(Groovy, Scala, etc.) designed from the start to support Lambda expressions. But java is used in an anonymous inner class instead. Finally, with a strong community strength, to find a compromise Lambda implementations, can achieve simple and compact structure of language.



Anonymous inner classes to the evolution of Lambda

Anonymous inner classes, that is, one with no name, exists in a class or method inside the class. When we need to use a class and just use once, create and use and two for the moment, we can choose to remain anonymous inner classes, and to cut steps we define the class.

Anonymous inner classes will inherit a hermit class or implement an interface, or anonymous inner class is an inherited class or subclass that implements this interface anonymous object. See the following example of anonymous inner classes

package com.java8;
/*
    定义和使用匿名内部类
 */
public class NoNameClass {
    public static void main(String[] args) {
​
        Model m = new Model(){
            @Override
            public void func() {
                System.out.println("方法的实现");
            }
        };
        m.func();
    }
}
// 需要被实现的接口
interface Model{
    void func();
}复制代码

Lambda equivalent codes

package com.java8;
/*
    定义和使用Lambda 简化代码
 */
public class NoNameClass {
    public static void main(String[] args) {
​
        Model m = new Model(){()->{
            System.out.println("方法的实现");
        }};
        m.func();
    }
}复制代码

It can be seen using a Lambda expression replaced anonymous inner class code, such code more simplified and compact.

grammar

(parameters) -> expression 或 (parameters) ->{ statements; }

  • Optional type declaration

    Do not need to declare the parameter type, the compiler can be unified identification parameter value.

  • The optional parameters in parentheses

    No need to define a parameter in parentheses, but a number of parameters need to be defined parentheses.

  • Optional braces

    If the body contains a statement, you do not need to use braces.

  • Optional return keyword

    If the subject is only one expression that returns a value, the compiler will automatically return value, braces need to specify a numerical expression returns

Lambda expressions Example:

expression description
() -> 1024 No arguments, returns a value of 1024
x -> 2 * x Receiving a parameter (type number), which returns a value twice
(x, y) -> x – y It accepts two parameters (number), and return to their difference
(int x, int y) -> x + y Receiving two int type integer, and return to their
(String s) -> System.out.print(s) Receiving a string object, and printed on the console, nothing is returned (return looks like void)

Lambda use form

When using the Lambda, implementation can have parameters, there may be a return value, if the parameter type is not specified, by the compiler itself inferred.

No reference return value

Generating an arbitrary integer between [1,10]

interface Model2{
    int func();
}
Model2 md2 = () -> {return (int)(Math.random()*10+1)};复制代码

Lambda的改写需要有对应的抽象方法,当没有参数时需要使用()占位,当表达式只有一行代码时,可以省略return和{}

Lambda is equivalent to the above:

Model2 md2 = () -> (int)(Math.random()*10+1);复制代码

Return value parameterized

Returns a string of the digital description.

interface Model3{
    String func(int a);
}
Model3 md3 = (int a) -> {
    return "This is a number " + a;
};复制代码

形参写在()内即可,参数的类型可以省略,此时将由编译器自行推断得出,同时还可以省略()

Lambda is equivalent to the above:

md3 =  a -> "This is a number " + a;复制代码

Type parameter is omitted, parentheses, brackets while the joint body and return to achieve together omitted.

With multiple parameters

Calculate two numbers in accordance with the operator input, and returns the result

interface Model4{
    String func(int a, int b, String oper);
}
 Model4 md4 = (a, b, s) -> {
      String res = "";
      if("+".equals(s)){
            res = ( a+b ) + "";
      }else if("-".equals(s)){
            res = ( a-b ) + "";
      }else if("*".equals(s)){
            res = ( a*b ) + "";
      }else if("/".equals(s)){
            res = ( a/b ) + ""; // 暂不考虑除0的情况
      }else{
            res =  "操作有失误";
      }
      return res;
 };
 System.out.println(md4.func(1,1,"+"));复制代码

Examples of the above plurality of parameters Lambda expressions, which omitted the type of each parameter, the compiler automatically inferred. When the body to achieve multiple statements {}should not be spared.


Lambda as a parameter

Before Java8, the interface can be passed as a parameter, interface class must provide examples of execution. From the beginning java8, Lambda can be used as an interface method implementation, passed as a parameter, either formally or actually eliminates the creation of the object. It makes the code more compact and simple and efficient.

  • Defined interfaces

    In the interface, there must be one and only one abstract method to determine the Lambda template

// 无参无返回值的方法
interface LambdaInterface1{
    void printString();
}
// 带参无返回值的方法
interface  LambdaInterface2{
    void printString(String str);
}复制代码
  • Receiving a parameter definition method

    In a method requires the use of an interface as a parameter

    // 无参
    public static void testLambda(LambdaInterface1 lam1){
      lam1.printString();
    }
    // 带参
    public static void testLambda2(String s,LambdaInterface2 lam2){
      lam2.printString(s);
    }复制代码
  • Lambda expressions as a parameter

// 无参Lambda作为参数
testLambda(()->{
    System.out.println("可以简单,可以复杂");
});
// 带参Lambda作为参数
testLambdaParam("hello",(a)->{
    System.out.println(a);
});复制代码


Lambda use variables

In Lambda can define their own local variables, local variables may be used in the method of the outer layer, the properties may also be used. It is not difficult to understand, since it is the realization of a method, just write a block of code, then use your own method of local variables and class attributes are also not too much.

public static void main(String[] args) {
    List<String> strs = new ArrayList<String>(){
        {
            add("aaa");
            add("bbb");
            add("ccc");
        }
    };
    int j = 1;
    strs.forEach((str)->{
        int i = 0;
        System.out.println(str + "  " + i + "  " + j);
    });
}复制代码


Lambda type inference

  • Type checking

    Lambda type is inferred from the context of the Lambda. The parameters in the process of the interface function formula Lambda expressions, each corresponding to the type of the return value. Lambda expressions of the type required, or the functional interface called Lambda achieve the target type.

  • Type inference

    Lambda to check whether a context for a specific, type inference Lambda parameter using the target type.


Lambda expressions combat

Hot Products Sort


Sort for you may not be familiar well-developed, if you did the original project electricity supplier, and I believe that record sort of goods under the electricity supplier operating very emotional scene, let's take a look at using Lambda selling merchandise ordered operating.

Here the test data to the test data, for example a mobile phone

/**
* 实际开发数据通常从数据库获取
* 这里使用测试数据
*/
Goods g01=new Goods(1,"小米9",1789,200, BigDecimal.valueOf(2500));
Goods g02=new Goods(2,"华为Mate20",5000,3000, BigDecimal.valueOf(7000));
Goods g03=new Goods(3,"OPPO R17",2000,2827, BigDecimal.valueOf(1500));
Goods g04=new Goods(4,"魅族 Note9",2000,1600, BigDecimal.valueOf(1600));
Goods g05=new Goods(5,"一加6T",8000,5000, BigDecimal.valueOf(3500));
List<Goods> goods= Arrays.asList(g01,g02,g03,g04,g05);复制代码
  • Collections.sort static methods to achieve the sort

 Collections.sort(goods,(g1,g2)->g1.getSale()-g2.getSale());复制代码
  • List.sort default sorting method to achieve the set


// 使用Lambda 对商品记录按销量进行排序
goods.sort((g1,g2)->g1.getSale()-g2.getSale());复制代码
  • Stream.sorted way to achieve the sort of elements

// 多个条件排序情况 Lambda 配置Stream  销量+价格排序  销量相等时按照价格排序
goods =goods.stream().sorted((g1,g2)->g1.getSale()-g2.getSale())
.sorted((g1,g2)->g1.getPrice().compareTo(g2.getPrice()))
.collect(Collectors.toList());复制代码

Log Output Optimization


For project development log printing module is not an acquisition, whether it is after the development phase of the project or the deployment line, log output information for developers as well as to the operation and maintenance personnel is an important reference index.

In scenarios where the user log output module UserService an example, the following is the code before optimization log output:

public String login(String userName, String userPwd) {
    logger.info("UserService 接收到参数-->" + userName + "," + userPwd);
    /**
     * 登录逻辑省略
     */
    return "login";
}复制代码

The log level to debug, easy viewing parameters of the back-end information received during the development phase. Careful analysis of the logging code here, you can see when the log level is set to info debug log output operations should not be performed, and when you call debug method for the string passed as a parameter corresponding to the required splicing operation here, will pass come. When the case of access to project activities to do in the mall situation here has the potential to become very bad: all the debug information output all at the same time have a lot of string concatenation operations affect the execution performance of the entire application.

In scenarios where the user log output module UserService an example, the log output code optimization

  • Log log output before the output level is determined

  • With Lambda delayed output log content

/**
 * 添加info方法
 *  判断日志打印级别
 *  当条件成立时 输出日志信息
 * @param logger
 * @param message
 */
public   void info(Log logger, Supplier<String> message){
    if(logger.isInfoEnabled()){
        logger.info(message.get());
    }
}
​
public String login(String userName, String userPwd) {
    //logger.info("UserService 接收到参数-->" + userName + "," + userPwd);
    // 延迟Lambda 表达式执行  只有确定
    info(logger,()->"UserService 接收到参数-->" + userName + "," + userPwd);
    return "login";
}复制代码

Lambda advantages and usage scenarios

Lambda expressions introducing a substituent anonymous inner classes, such that the code becomes simple and compact, while an inert Lambda characteristics of development can be improved at the time of the execution performance of the application.

For Lambda application scenario, the code structure is typically used in conjunction with a function interface, so that the development is carried out for the programming functions, a new idea is introduced Java8 - Functional Programming (description will follow). While also binding the front interface default method mentioned withdrawals to application development.


Le byte original articles, please indicate the source and author!

More technical data byte music tutorial invited: Le byte Tencent classroom


Guess you like

Origin juejin.im/post/5cf23b79f265da1bb564e013