Java8 Lambda 语法结构、方法引用

什么是Lambda表达式

Lambda表达式可以看做是一个匿名类。将一个Lambda表达式做为参数传递给方法,行为参数化,就实现了函数式编程。
在没有Lambda之前,要实现函数式编程就需要使用匿名类,如果用Lambda会使得代码更加简洁、清晰。

举个例子:
如果要实现传递方法的方式实现加法和减法,可以使用下面匿名类的写法:

  public class Demo0 {

    //两个参数的运算
    interface MathOperation {
        double operation(double a, double b);
    }

    public static void main(String[] args) {
        //加法
        MathOperation add=new MathOperation() {
            @Override
            public double operation(double a, double b) {
                return a+b;
            }
        };

        //减法
        MathOperation sub=new MathOperation() {
            @Override
            public double operation(double a, double b) {
                return a-+b;
            }
        };
        System.out.println("20+10:" + add.operation(20, 10));
        System.out.println("20-10:" + sub.operation(20, 10));
    }
}

如果用Lambda表达式实现,可以写作下面的方式:

   public class Demo1 {

    //两个参数的运算
    interface MathOperation {
        double operation(double a, double b);
    }

    public static void main(String[] args) {

        //加法
        MathOperation add = (double a, double b) -> a + b;

        //减法
        MathOperation sub = (a, b) -> a - b;

        System.out.println("20+10:" + add.operation(20, 10));
        System.out.println("20-10:" + sub.operation(20, 10));
    }
}

这里将内部类的变为了Lambda表达式,简化了代码。

基础语法结构

Lambda的表达式结构如下:

(variable)->action
  1. variable:方法的变量名称,可以有多个变量,如果只有一个变量,可以将小括号省略。
  2. action:是方法体,是自己写的代码逻辑的部分。可以是一行代码或者多行代码,如果只有一行代码,可以不要花括号,如果是多行代码,需要用花括号括起来。
  3. -> : 这个符号用于将变量和方法体分割开来。

举例

public class Demo1 {

    //没有参数的运算
    interface NoParamOperation {
        double operation();
    }

    //一个参数的运算
    interface SingleParamOperation {
        int operation(int a);
    }

    //两个参数的运算
    interface MathOperation {
        double operation(double a, double b);
    }

    public static void main(String[] args) {

        //======几种Lambda表达式的写法=============

        //得到PI值(没有参数,直接返回)
        NoParamOperation pi = () -> Math.PI;

        //得到自然常数 (没有参数,直接返回,如果有花括号,要写上显式的加上return)
        NoParamOperation e = () -> {
            return Math.E;
        };

        //求平方(如果参数是一个,可以省略小括号)
        SingleParamOperation square = a -> a * a;

        //求立方(可以指定参数的类型,如果没有编译器会自动推算)
        SingleParamOperation cubic = (int a) -> a * a * a;

        //加法(如果多个参数,就必须添加上小括号)
        MathOperation add = (double a, double b) -> a + b;

        //减法(多个参数,也可以不指定参数的数据类型)
        MathOperation sub = (a, b) -> a - b;

        //乘法(一行代码,函数体上也可以写上花括号)
        MathOperation mult = (double a, double b) -> {
            return a * b;
        };

        //除法(如果函数体有多行,就必须有花括号)
        MathOperation div = (a, b) -> {
            if (b != 0) {
                return a / b;
            } else {
                return 0;
            }
        };
        
        System.out.println("PI的值" + pi.operation());
        System.out.println("自然常数E的值:" + e.operation());

        System.out.println("10的平方:" + square.operation(10));
        System.out.println("10的立方:" + cubic.operation(10));

        System.out.println("20+10:" + add.operation(20, 10));
        System.out.println("20-10:" + sub.operation(20, 10));
        System.out.println("20*10:" + mult.operation(20, 10));
        System.out.println("20/10:" + div.operation(20, 10));
    }
}

更简单的一种表示方式

方法引用是Lambda表达式的一种简写,格式为:

ObjectRef::methodName
  1. ObjectRef可以是类名、实例名。
  2. :: 符号是方法引用符号。
  3. methodName 是引用的方法名。

有三种方法引用类型:静态方法引用、实例方法引用、构造方法引用

1、静态方法引用
package javademo.lambda.MathOperationDemo;

public class Demo2Util {
    static double formatPrint(String format, double a, double b) {
        double r = a + b;
        System.out.format(format, r);
        return r;
    }
}
package javademo.lambda.MathOperationDemo;

public class Demo2 {
    //两个参数的运算
    interface MathOperation {
        double operation(String format, double a, double b);
    }
    public static void main(String[] args) {
        //内部类方式,方法中只调用了一个静态方法formatPrint
        MathOperation add = new MathOperation() {
            @Override
            public double operation(String format, double a, double b) {
                return Demo2Util.formatPrint(format, a, b);
            }
        };

        //Lambda方式,调用了静态方法
        MathOperation add1 = (f, a, b) -> Demo2Util.formatPrint(f, a, b);

        //静态方法引用方式,代码更紧凑简洁
        MathOperation add2 = Demo2Util::formatPrint;

        add.operation("内部类方式:%f", 20, 10);
        add1.operation("Lambda方式:%f", 20, 10);
        add2.operation("方法引用方式:%f", 20, 10);
    }
}
2、实例方法引用

如果方法中是调用某一个对象的方法,可以简写为方法引用的方式。

package javademo.lambda.MathOperationDemo;
public class Demo3Helper {
    //这里将方法放到一个类中
    public double formatPrint(String format, double a, double b) {
        double r = a + b;
        System.out.format(format, r);
        return r;
    }
}
package javademo.lambda.MathOperationDemo;

public class Demo3 {
    //两个参数的运算
    interface MathOperation {
        double operation(String format, double a, double b);
    }
    public static void main(String[] args) {
        Demo3Helper helper = new Demo3Helper();

        //匿名类的方式,方法中调用了helper对象的一个方法。
        MathOperation add1 = new MathOperation() {
            @Override
            public double operation(String format, double a, double b) {
                return helper.formatPrint(format, a, b);
            }
        };
        //Lambda方式,方法体内只是调用一个对象的方法。
        MathOperation add2 =(f,a,b)-> helper.formatPrint(f,a,b);
        //这个时候,就可以简写为方法引用
        MathOperation add3 = helper::formatPrint;

        add1.operation("匿名类的方式:%f\n", 20, 10);
        add2.operation("Lambda方式:%f\n", 20, 10);
        add3.operation("方法引用方式:%f\n", 20, 10);
    }
}
3、构造方法引用

当接口的方法里操作是实例化一个对象时,比如下面例子里,只是new 一个对象,对应的Lambda表达式可以简化为构造方法引用方式。

举例:

package javademo.lambda.MathOperationDemo;

public class Demo5 {

    //计算器类
    static class Calculator {
        //计算器类,一个参数的构造函数
        public Calculator(String name) {
            this.name = name;
        }

        //计算器类,两个参数的构造函数
        public Calculator(Integer id,String name)
        {
            this.id=id;
            this.name=name;
        }
        private Integer id;
        private String name;

        public Integer getId() {
            return id;
        }

        public void setId(Integer id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    //计算器接口,有一个创建计算器的方法
    interface ICalculator {
        Calculator create(String name);
    }
    //计算器接口,有两参数个创建计算器的方法
    interface ICalculator2 {
        Calculator create(Integer id,String name);
    }

    public static void main(String[] args) {
        //第1种方式:内部类方式创建电脑对象和中国算盘对象
        ICalculator pc1 = new ICalculator() {
            @Override
            public Calculator create(String name) {
                return new Calculator(name);
            }
        };
        ICalculator2 pc11=new ICalculator2() {
            @Override
            public Calculator create(Integer id, String name) {
                return new Calculator(id,name);
            }
        };
        
        //第2种方式:用Lambda表达式创建
        ICalculator pc2 = (name) -> new Calculator(name);
        ICalculator2 pc22=(id,name)->new Calculator(id,name);

        //第3种方式:用方法引用方式进一步简化Lambda表达式。
        ICalculator pc3 = Calculator::new;
        ICalculator2 pc33=Calculator::new;

        Calculator c1 = pc1.create("电脑1");
        Calculator c11 = pc11.create(11,"电脑11");
        Calculator c2 = pc2.create("电脑2");
        Calculator c22=pc22.create(22,"电脑22");
        Calculator c3 = pc3.create("电脑3");
        Calculator c33=pc33.create(33,"电脑33");
    }
}
发布了74 篇原创文章 · 获赞 74 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/chybin500/article/details/86590962