2021-04-12

本文介绍了Java 1.8中lambda表达式的概念、语法、优化写法,以及函数式接口的应用,包括无参无返回、有参无返回和有参有返回的示例。同时涵盖了方法引用、构造器引用和数组引用等高级用法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

jdk1.8新特性知识点:

一、lambda表达式
lambda表达式为匿名内部类的简写,类似于匿名内部类的语法糖;但又区别于匿名内部类(后文会讲解)。

匿名内部类特点:

基于多态(多数基于接口编程)
实现类无需名称
允许多个抽象方法
Lambda的语法简洁,没有面向对象复杂的束缚。
特点:

使用Lambda必须有接口,并且接口中有且仅有一个抽象方法。
只有当接口中的抽象方法存在且唯一时,才可以使用Lambda,但排除接口默认方法以及声明中覆盖Object的公开方法。
使用Lambda必须具有上下文推断。
也就是方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例。
备注:有且仅有一个抽象方法的接口,称为“函数式接口”。
标准格式由三部分组成:

一些参数
一个箭头
一段代码
格式:
(参数列表)->{一些重要方法的代码};
():接口中抽象方法的参数列表,没有参数,就空着;有参数就写出参数,多个参数用逗号分隔。
->:传递:把参数传递给方法体{}
{}:重写接口的抽象方法的方法体
箭头操作符的左侧对应接口中参数列表(lambda表达式的参数列表),
箭头右侧为该抽象方法的实现(lambda表达式所需执行的功能)。
**lambda优化写法:**
可以推导的,都可以省略(凡是能根据上下文推导出来的内容,都可以省略不写):

(参数列表):括号中参数列表的数据类型,可以省略不写
(参数列表):括号中的参数只有一个,那么类型和()都可以省略
 {一些代码} :如果{}中的代码只有一行,无论是否有返回值,都可以省略({},return,分号)

注意:要省略{},return,分号 必须一起省略

public class MyLambda {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"新线程创建了");
            }
        }).start();

        //使用Lambda
        new Thread(()->{
            System.out.println(Thread.currentThread().getName()+"新线程创建了");
        }).start();

        //优化lambda
        new Thread(()->System.out.println(Thread.currentThread().getName()+"新线程创建了")).start();
    }
}

1.1无参数,无返回

()->System.out.println("hello lambda")

Cook:

public interface Cook {
    public abstract void makeFood();		
}
public class Demo01Cook {

    public static void main(String[] args) {
        invokeCook(new Cook() {
            public void makeFood() {
                System.out.println("做饭。。。");
            }
        });
        //使用Lambda
        invokeCook(()->{
            System.out.println("做饭。。。");
        });

        //优化lambda
        invokeCook(()-> System.out.println("做饭。。。"));
    }

    public static void invokeCook(Cook cook){
        cook.makeFood();
    }
}

1.2 有参数,无返回

x->System.out.println("hello lambda")
import java.util.function.Consumer;

/**
 * Created by hongcaixia on 2019/10/31.
 */
public class Demo2 {

    public static void main(String[] args) {
        Consumer<String> consumer = x-> System.out.println(x);
        consumer.accept("有参数无返回");
    }
}

1.3 有参数,有返回

(Person p1,Person p2)->{ return p1.getAge()-p2.getAge(); }
package com.hcx.lambda;

import java.util.Arrays;
import java.util.Comparator;

/**
 * Created by hongcaixia on 2019/10/26.
 */
public class MyArrays {

    public static void main(String[] args) {
        Person[] arr = {new Person("陈奕迅",40),
                        new Person("钟汉良",39),
                        new Person("杨千嬅",38)};


        //对年龄进行排序

        Arrays.sort(arr, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge()-o2.getAge();
            }
        });

        //使用lambda
        Arrays.sort(arr,(Person p1,Person p2)->{
            return p1.getAge()-p2.getAge();
        });

        //优化lambda
        Arrays.sort(arr,(p1,p2)->p1.getAge()-p2.getAge());

        Arrays.sort(arr,Comparator.comparing(Person::getAge));

        for (Person p:arr){
            System.out.println(p);
        }
    }
}

Lmabda表达式的语法总结: () -> ();

前置语法
无参数无返回值() -> System.out.println(“Hello WOrld”)
有一个参数无返回值(x) -> System.out.println(x)
有且只有一个参数无返回值x -> System.out.println(x)
有多个参数,有返回值,有多条lambda体语句(x,y) -> {System.out.println(“xxx”);return xxxx;}
有多个参数,有返回值,只有一条lambda体语句(x,y) -> xxxx

口诀:左右遇一省括号,左侧推断类型省
注:当一个接口中存在多个抽象方法时,如果使用lambda表达式,并不能智能匹配对应的抽象方法,因此引入了函数式接口的概念

二、函数式接口

一、概念
函数式接口在Java中是指:有且仅有一个抽象方法的接口。
二、格式
只要确保接口中有且仅有一个抽象方法即可:

修饰符 interface 接口名称 {
    public abstract 返回值类型 方法名称(可选参数信息);
}

由于接口当中抽象方法的public abstract是可以省略的,所以定义一个函数式接口很简单:

public interface MyFunctionalInterface {
    //抽象方法只有一个
	void method();
    //可以含有默认方法
    public default void method_1() {
    }
}

自定义函数式接口(无参无返回值)
对于刚刚定义好的MyFunctionalInterface函数式接口,典型使用场景就是作为方法的参数:

public class Demo04 {
    public static void main(String[] args) {
        show(() -> System.out.println("lambda执行了。。。。"));
    }
    public static void show(MyFunctionalInterface mi) {
        mi.method();// 调用自定义的函数式接口方法
    }
}

自定义函数式接口(有参有返回)
请定义一个函数式接口Sumable,内含抽象sum方法,可以将两个int数字相加返回int结果。使用该接口作为方法的参数,并进而通过Lambda来使用它。

public interface Sumable {
    int sum(int a, int b);
}
public class Demo05 {
    public static void main(String[] args) {
        getSum(150,250,(a,b) -> a + b);
    }
    private static void getSum(int a,int b,Sumable sumable){
        int sum = sumable.sum(a, b);
        System.out.println(sum);
    }
}

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

 可以将方法引用理解为 Lambda 表达式的另外一种表现形

如下三种主要使用情况:
1、对象引用::实例方法名
2、类::静态方法名
3、类::实例方法名(lambda参数列表中第一个参数是实例方法的调用者,第二个参数是实例方法的参数时可用)**

public void test() {
	
	/*注意:
	 *1.lambda体中调用方法的参数列表与返回值类型,要与函数式接口中抽象方法的函数列表和返回值类型保持一致
	 *2.若lambda参数列表中的第一个参数是实列方法的调用者,而第二个参数是实例方法的参数时,可以使用ClassName::meth
	 */

	 Consumer<Integer> con = (x) -> System.out.println(x);
        con.accept(100);

        // 方法引用-对象::实例方法
        Consumer<Integer> con2 = System.out::println;
        con2.accept(200);

        // 方法引用-类名::静态方法名
        BiFunction<Integer, Integer, Integer> biFun = (x, y) -> Integer.compare(x, y);
        BiFunction<Integer, Integer, Integer> biFun2 = Integer::compare;
        Integer result = biFun2.apply(100, 200);

        // 方法引用-类名::实例方法名
        BiFunction<String, String, Boolean> fun1 = (str1, str2) -> str1.equals(str2);
        BiFunction<String, String, Boolean> fun2 = String::equals;
        Boolean result2 = fun2.apply("hello", "world");
        System.out.println(result2);
    }

(b)构造器引用
格式:ClassName::new

public void test2() {

        // 构造方法引用  类名::new
        Supplier<Employee> sup = () -> new Employee();
        System.out.println(sup.get());
        Supplier<Employee> sup2 = Employee::new;
        System.out.println(sup2.get());

        // 构造方法引用 类名::new (带一个参数)
        Function<Integer, Employee> fun = (x) -> new Employee(x);
        Function<Integer, Employee> fun2 = Employee::new;
        System.out.println(fun2.apply(100));
 }

c)数组引用
格式:Type[]::new

public void test(){
        // 数组引用
        Function<Integer, String[]> fun = (x) -> new String[x];
        Function<Integer, String[]> fun2 = String[]::new;
        String[] strArray = fun2.apply(10);
        Arrays.stream(strArray).forEach(System.out::println);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值