Java8中的Lambda表达式理解与使用

目录

一、什么是Lambda表达式

二、Lambda表达式和匿名函数的差别

三、Lambda表达式的4种方法引用

第一种:静态方法引用

第二种:实例方法引用

第三种:构造方法引用

第四种:特殊方法引用

四、拓展


一、什么是Lambda表达式

        Lambda表达式是Java 8引入的一个特性,它允许你以匿名函数的方式写出更简洁的代码,所以说,也可以理解为它和特定匿名函数是一个意思,只是写法上不同,更加的简洁(当然看不习惯的反而可能觉得复杂)。

        Lambda表达式的基本语法是 (parameters) -> expression,其中 -> 表示将参数映射到表达式上。

        Lambda表达式可以用于实现函数式接口,即只包含一个抽象方法接口‌

        上面红色字体说明了Lambda表达式与普通匿名函数的区别,它所需要的条件比较严格,并不适合简化所有的匿名函数。

二、Lambda表达式和匿名函数的差别

        上面已经说明了Lambda表达式和匿名函数一样,都可以实现函数式接口,但只能是包含唯一一个抽象方法的,并且是接口interface类。

public class LambdaTest {
	public static void main(String[] args) {
        checkId1("1", User::getUserIdStatic); //使用引用类静态方法,得到的id与User类静态值有关
        User user = new User("2");
        checkId1("1", user::getUserId); //使用引用实例对象方法,得到的id与user实例有关
        checkId1("1", ()-> user.getUserId()); //使用正常Lambda表达式(简化了{}和return),->后加上{}可以正常编写方法实现内容
        checkId2("1", new ICommonFun(){ //使用匿名函数,因为这个接口的抽象方法数量大于1个
            @Override
            public String getId() {
                return user.getUserId();
            }

            @Override
            public void setId(String id) {
            }
        });
    }

    public static void checkId1(String id, ILambdaFun iLambdaFun){
        if (id.equals(iLambdaFun.getId())){
            System.out.println("id相等");
        }else{
            System.out.println("id不相等");
        }
    }

    public static void checkId2(String id, ICommonFun iCommonFun){
        if (id.equals(iCommonFun.getId())){
            System.out.println("id相等");
        }else{
            System.out.println("id不相等");
        }
    }

    interface ILambdaFun {
        String getId(); // 方法参数数量为0个,所以lambda表达式为()->{}
    }
    interface ICommonFun {
        String getId();
        void setId(String id); //多了这个方法,所以无法使用Lambda表达式来实现这个接口。去掉或改为非抽象方法才可以使用Lambda表达式来实现这个接口。
    }


    static class User {
        private String id;
        private static String idStatic = "1";
        User(String id){
            this.id = id;
        }
        private String getUserId () {
            return id;
        }
        private static String getUserIdStatic () {
            return idStatic;
        }
    }
}

// 运行结果
//id相等
//id不相等
//id不相等
//id不相等

三、Lambda表达式的4种方法引用

        上面的代码例子中,在使用Lambda表达式时,使用了2种方法引用,和Lambda正常表达式。Lambda表达式总共有4种方法引用:

1,静态方法引用(上面代码例子有使用过)

2,实例方法引用(上面代码例子有使用过)

3,构造方法引用

4,特殊方法引用

第一种:静态方法引用

引用语法:类名::方法名,如User::getIdStatic()

注意事项:
        函数式接口(interface类)中抽象方法参数列表是什么样的,被引用的方法参数列表也要是一样的;
        接口的抽象方法没有返回值,被引用的方法返回值可有可无;
        接口的抽象方法有返回值,被引用的方法必须有相同类型的返回值。

第二种:实例方法引用

引用语法:对象名::非静态方法名,如:user::getId()

注意事项:
        函数式接口(interface类)中抽象方法参数列表是什么样的,被引用的方法参数列表也要是一样的;

        接口的抽象方法没有返回值,被引用的方法返回值可有可无;

        接口的抽象方法有返回值,引用的方法必须有相同类型的返回值。

第三种:构造方法引用

引用语法:类名::new,如:String::new

注意事项:
        函数式接口(interface类)中抽象方法参数列表是什么样的,被引用的构造方法参数列表也要是一样的。

第四种:特殊方法引用

引用语法:类名::实例方法名,如User::getId()

注意事项:
        在抽象方法中,第一个参数可以作为被引用的实例方法(如getId())的调用者(如User实例对象),就可以简化。所以这种抽象方法必须有至少一个参数,且第一个参数是可以调用实例方法的对象;除去第一个参数的其余参数组成的参数列表,在第一个参数代表的对象类里,必须有对应的非静态实例方法。(如,抽象方法为void setObject(User user,String v1),则User类里必须有fun(String v1)方法,方法返回值同第一二种要求。)

public class LambdaTest {
    public static void main(String[] args) {
        checkId1("1", User::getUserId); // 看着像引用静态方法
    }

    public static void checkId1(String id, ILambdaFun iLambdaFun){
        if (id.equals(iLambdaFun.getObject(new User("1")))){ // 使用函数实例的抽象方法时,需要根据参数传入实例对象
            System.out.println("id相等");
        }else{
            System.out.println("id不相等");
        }
    }

    interface ILambdaFun {
        Object getObject(User user); // 抽象方法里有且只有一个参数
    }

    static class User {
        private String id;
        private static String idStatic = "1";
        User(String id){
            this.id = id;
        }
        private String getUserId () {
            return id;
        }
        private static String getUserIdStatic () {
            return idStatic;
        }
    }
}

四、拓展

        Java中一些可使用Lambda表达式的接口

  • Consumer<T>:接受一个输入参数并不返回结果。
  • Supplier<T>:不接受任何参数,返回一个结果。
  • Function<T, R>:接受一个参数并返回一个结果。
  • Predicate<T>:接受一个参数,返回一个布尔值。
public class LambdaTest {
    public static void main(String[] args) {
        List<User> userList = new ArrayList<>();
        User user1 = new User("1");
        userList.add(user1);
        userList.add(new User("2"));
        HashMap<String,User> map = listToMap(userList, User::getUserId); //需要其它属性值作为Map的Key,直接换一个引用方法即可
        System.out.println(map.get("1"));
        System.out.println(map.get("2"));
    }

    public static HashMap<String, User> listToMap(List<User> userList, Function<User, String> function){
        HashMap<String, User> userMap = new HashMap<>();
        userList.forEach((item)->{
            userMap.put(function.apply(item), item);
        });
        return userMap;
    }

    public static class User {
        private String id;
        private static String idStatic = "1";
        User(String id){
            this.id = id;
        }
        private String getUserId () {
            return id;
        }
        private static String getUserIdStatic () {
            return idStatic;
        }

        @Override
        public String toString() {
            return "User{id:"+id+"}";
        }
    }
}

// 运行结果
//User{id:1}
//User{id:2}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

兴趣广泛的程序猿

有钱的捧个钱场,谢谢各位!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值