jdk 8特性 - Lambda表达式,函数式接口

#简介

jdk8的好处

  • 1.速度更快
  • 2.代码更少(增加新的语法Lambda表达式)
  • 3.强大的Stream API
  • 4.便于并行
  • 5.最大化减少空指针异常 Optional

其中最为核心的为 Lambda 表达式与Stream API

1. Lambda 表达式

Lambda 是一个 匿名函数,我们可以把 Lambda
表达式理解为是 一段可以传递的代码(将代码
像数据一样进行传递)。可以写出更简洁、更
灵活的代码。作为一种更紧凑的代码风格,使
Java的语言表达能力得到了提升

1.1 从匿名类到 Lambda 的转换

匿名内部类
lambda 表达式

1.2 参数传递

传统参数传递
lambda参数传递
##1.3 Lambda表达式语法

Lambda 表达式在Java 语言中引入了一个新的语法元
素和操作符。这个操作符为 “- -> >” , 该操作符被称
为 Lambda 操作符或剪头操作符。它将 Lambda 分为
两个部分:
左侧:指定了 Lambda 表达式需要的所有参数
右侧:指定了 Lambda 体,即 Lambda 表达式要执行
的功能。

  • 语法格式一 : 无参,无返回值,Lambda 体只需一条语句
    无参,无返回值

  • 语法格式二 :Lambda 需要一个参数(有参,无返回值)
    有参,无返回值

  • 语法格式三 :Lambda 只 需 要一个参数时,参数的小括号可以省略
    一个参数可省略小括号

  • 语法格式四 :Lambda 需要两个参数,并且有返回值
    有参,有返回值

  • 语法格式五 : 当 Lambda 体只有 一条 语句时,return 与大括号 可以省略
    一条语句可省略大括号

  • 语法格式六:数据类型可以省略, 因为可由编译器推断得出,称为"类型推断"
    image.png

上述 Lambda 表达式中的参数类型都是由编译器推断
得出的。Lambda 表达式中无需指定类型,程序依然可
以编译,这是因为 javac 根据程序的上下文,在后台
推断出了参数的类型。Lambda 表达式的类型依赖于上
下文环境,是由编译器推断出来的。这就是所谓的
“类型推断”

2. 函数式接口

  • 只包含一个抽象方法的接口,称为 函数式接口
  • 你可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda
    表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方
    法上进行声明)。
  • 我们可以在任意函数式接口上使用 @FunctionalInterface 注解,
    这样做可以检查它是否是一个函数式接口,同时 javadoc 也会包
    含一条声明,说明这个接口是一个函数式接口。

##2.1 自定义函数式接口
自定义
###2.1.1 函数式接口中使用泛型
函数式接口中使用泛型
##2.2 作为参数传递 Lambda
作为参数传递 Lambda
作为参数传递 Lambda

作为递 参数传递 Lambda 将 表达式:为了将 Lambda 表达式作为参数传递,接
收 Lambda 该 表达式的参数类型必须是与该 Lambda 表达式兼容的函数式接口
的类型。
##4.Java内置四大核心函数是接口
| 函数式接口 | 参数类型 | 返回类型 | 用途 |
| :-------: |:-------------? :-----? :-----?
| Consumer
消费型接口 | T | void | 对类型为T的对象应用操作,包含方法:void accept(T t) |
| Supplier
供给型接口 | 无 | T | 返回类型为T的对象,包含方法:T get(); |
| Function<T, R>
函数型接口 | T | R | 对类型为T的对象应用操作, 并返回结果.结果是R类型的对象.包含方法: R apply(T t); |
| Predicate
断定型接口 | T | boolean | 确定类型为T的对象是否满足某约束, 并返回Boolean值. 包含方法Boolean test(T t); |

public class Employee {

    private int id;
    private String name;
    private int age;
    private double salary;

    public Employee() {
    }

    public Employee(String name) {
        this.name = name;
    }

    public Employee(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Employee(int id, String name, int age, double salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public String show() {
        return "测试方法引用!";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + id;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        long temp;
        temp = Double.doubleToLongBits(salary);
        result = prime * result + (int) (temp ^ (temp >>> 32));
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Employee other = (Employee) obj;
        if (age != other.age)
            return false;
        if (id != other.id)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        if (Double.doubleToLongBits(salary) != Double.doubleToLongBits(other.salary))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "Employee [id=" + id + ", name=" + name + ", age=" + age + ", salary=" + salary + "]";
    }

}

3. 方法引用与构造器引用

##3.1 方法引用

当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!
(实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致!)
方法引用:使用操作符 “ ::” 将方法名和对象或类的名字分隔开来。
如下三种主要使用情况 :

  • 对象 :: 实例方法
  • 类 :: 静态方法
  • 类 :: 实例方法

3.2 例子

        PrintStream ps = System.out;
        Consumer<String> con = (str) -> ps.println(str);
        con.accept("Hello World!");
     
        Consumer<String> con2 = ps::println;
        con2.accept("Hello Java8!");

Hello World!
Hello Java8!

  • 3.2.1 对象的引用 :: 实例方法名
       Employee emp = new Employee(101, "zhangsan", 19, 99.9);

        Supplier<String> sup = () -> emp.getName();
        System.out.println(sup.get());

        System.out.println("-------------");

        Supplier supplier = emp :: getName;
        System.out.println(supplier.get());

zhangsan

zhangsan

  • 3.2.2 类名 :: 静态方法名
@Test
    public void test03() {
        BiFunction<Double, Double, Double> fun = (x, y) -> Math.max(x,y);
        System.out.println(fun.apply(1.34, 20.22));
        System.out.println("-----");
        BiFunction<Double, Double, Double> function = Math:: max;
        System.out.println(function.apply(34.22,10.33));
    }

20.22

34.22

    @Test
    public void test04(){
        Comparator<Integer> com = (x, y) -> Integer.compare(x,y);
        System.out.println(com.compare(1, 2));

        Comparator<Integer> comparator = Integer::compare;
        System.out.println(comparator.compare(3,2));

    }

-1
1

  • 3.2.3 类名 :: 实例方法名
    @Test
    public void test05() {
        //判断是否相同
        BiPredicate<String, String> bp = (x, y) -> x.equals(y);
        System.out.println(bp.test("xu", "yu"));

        System.out.println("----");

        BiPredicate<String, String> bp1 =String:: equals;
        System.out.println(bp1.test("xu", "yu"));

        System.out.println("----");

        Function<Employee, String> fun = (e) -> e.show();
        System.out.println(fun.apply(new Employee()));

        System.out.println("----");

        Function<Employee, String> fun1 = Employee::show;
        System.out.println(fun1.apply(new Employee()));

    }

false
----
true
----
测试方法引用!
----
测试方法引用!

    @Test
    public void test06() {
        Supplier<Employee> sup = () -> new Employee();
        System.out.println(sup.get());

        System.out.println("---");

        Supplier<Employee> sup2 = Employee::new;
        System.out.println(sup2.get());
    }

Employee [id=0, name=null, age=0, salary=0.0]

Employee [id=0, name=null, age=0, salary=0.0]

3.3 构造器引用

  • 3.3.1 简介

格式: ClassName :: new
与函数式接口相结合,自动与函数式接口中方法兼容。
可以把构造器引用赋值给定义的方法,与构造器参数
列表要与接口中抽象方法的参数列表一致!

  • 3.3.2 例子
     @Test
    public void test07() {
        Function<String, Employee> fun = Employee::new;
        System.out.println(fun.apply("xu"));

        BiFunction<String, Integer, Employee> fun2 = Employee::new;
        System.out.println(fun2.apply("xu", 2));
    }

Employee [id=0, name=xu, age=0, salary=0.0]
Employee [id=0, name=xu, age=2, salary=0.0]

##3.4 数组引用

  • 3.4.1简介

格式type[] :: new

    @Test
    public void test08() {
        Function<Integer, String[]> fun = (args) -> new String[args];
        String[] strs = fun.apply(10);
        System.out.println(strs.length);

        System.out.println("------");

        Function<Integer, Employee[]> fun2 = Employee[]::new;
        Employee[] employees = fun2.apply(20);
        System.out.println(employees.length);

    }

10
------
20

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值