lambda表达式

业务开发中有个很常见的场景:

比如我现在有个List<Student> list 集合,我现在只想获取id集合或者我想做成Map<sId,sName>的格式,以便我在下面的逻辑里能够直接通过Map.get(sId)获取业务数据。

1. 代码里循环list转成map。

2.做成工具类,传入list,返回想要的key,value,方便。

但是好痛苦,,工具类要不断复制,或者有maven私服还好点,但是你到别的公司,是不是还得写新的?

Java8的lambda就能解决这个问题,一行搞定。今天来学习下。

函数式接口:

如果一个接口只有一个抽象方法,那么该接口就是函数式接口。

Java8里面接口不再只有抽象方法了,还有静态方法,默认方法。这里面的东西暂时不去管,先知道这么个概念。

接口静态方法:需要在接口里进行实现,通过接口名.方法名直接调用。

接口默认方法:需要在接口里进行实现,所有接口的实现类都默认继承该方法,子类可重写。

接口抽象方法:接口中没有实现的方法。

FunctionalInterface注解:

如果一个接口符合函数式接口的定义,那么就可以在接口上定义FunctionalInterface注解,用来表示这个接口是一个函数式接口,并且会按照函数式接口的规范在编译时进行检查。

如果一个接口只有一个抽象方法,但是没有这个注解,编译器依然会将该接口看做是函数式接口。

Lambda表达式:

那么我们知道了函数式接口,怎么理解Lambda表达式呢? 在Java里,一切皆是对象,在Java7的世界里,我们想要用一个接口的方法时,有两种方式:

1.定义一个实现类,重写方法。

2.定义一个匿名内部类,直接写在我们原有代码里,不需要新建一个实现类了。

那么Java8和这个类比的话,我们不需要写实现类,不需要写匿名内部类,我们用什么去做呢?就是Lambda表达式了。因此我的理解就是Lambda表达式 就是一个对象,它的对象类型就是 函数式接口其实就是在说Lambda表达式就是一个接口的实现。那么只要一个对象时函数式接口的实现,就可以用Lambda表达式来写

Lambda语法:

1.1基本语法

(Type1 param1, Type2 param2, ..., TypeN paramN) -> {
  statment1;
  statment2;
  //.............
  return statmentM;
}

1.2 单参数写法

param1 -> {
  statment1;
  statment2;
  //.............
  return statmentM;
}
List<String> nameList = list.stream().map(student -> {return student.getName();}).collect(Collectors.toList());

当左边的参数只有一个时,可以省略括号,比如有个Student list集合,我需要取一个List<String>name 的集合时,就可以写成上面的样子。

1.3单语句写法

param1 -> statment
List<String> nameList = list.stream().map(student -> student.getName()).collect(Collectors.toList());

单参数,单语句时写法最简洁。

1.4方法引用写法

上面是参数和语句的简洁写法,另外方法的调用上还能由其他简洁写法。

Class or instance :: method

可以看见,类名 + 方法名

List<String> nameList = list.stream().map(Student :: getName).collect(Collectors.toList());

1.5 可以外部变量

比如我要给每个Student 的名字加上后缀"同学"。

        String suffix = "同学";
        List<String> nameList = list.stream().map(student -> student.getName() + suffix).collect(Collectors.toList());

此处suffix被优化成了final变量,final变量特点是不可变(引用不可变,不是内容不可变)。

1.6 this的使用

public static void main(String[] args) {

        Student s1 = new Student();
        s1.setId(1);
        s1.setName("测试1");

        Student s2 = new Student();
        s2.setId(2);
        s2.setName("测试2");

        List<Student> list = new ArrayList<>();
        list.add(s1);
        list.add(s2);

        List<String> listName = new Main().getName(list);

        System.out.println(listName);

    }

    private List<String> getName(List<Student> list){

        return list.stream().map(student -> student.getName() + this.getSuffix()).collect(Collectors.toList());

    }

    private String getSuffix(){
        return "同学";
    }

this的用处依然没变。

2.1 方法引用和构造器引用

1.4 介绍了可以直接Class:: method,这就是Java8的语法糖。

方法引用:

类名 ::类方法
类名 ::实例方法
对象 ::实例方法

现有一个Student类:

public class Student {

    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;
    }

    public Student(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public static int compareByNameStatic(Student s1, Student s2) {
        return s1.getName().compareToIgnoreCase(s2.getName());
    }

    public int compareByNameInstance1(Student s1, Student s2) {
        return s1.getName().compareToIgnoreCase(s2.getName());
    }
    
    public int compareByNameInstance(Student s2) {
        return this.getName().compareToIgnoreCase(s2.getName());
    }
}

类名 ::类方法

public class Test {

    public static void main(String[] args) {

        Student s1 = new Student(7,"测试7");
        Student s2 = new Student(2,"测试2");
        Student s3 = new Student(1,"测试1");
        Student s4 = new Student(5,"测试5");

        List<Student> list = new ArrayList<>();
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s4);

        //写法一
        list.sort((temp1,temp2) -> Student.compareByNameStatic(temp1,temp2));

        //优化写法二
        list.sort(Student :: compareByNameStatic);

        list.forEach(student -> System.out.println(student.getName()));

    }
}

类名 ::实例方法

public class Test {

    public static void main(String[] args) {

        Student s1 = new Student(7,"测试7");
        Student s2 = new Student(2,"测试2");
        Student s3 = new Student(1,"测试1");
        Student s4 = new Student(5,"测试5");

        List<Student> list = new ArrayList<>();
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s4);

        //写法一
        list.sort((st,temp2) -> st.compareByNameInstance(temp2));

        //优化二
        list.sort(Student :: compareByNameInstance);

        list.forEach(student -> System.out.println(student.getName()));

    }
}

对象 ::实例方法

public class Test {

    public static void main(String[] args) {

        Student s1 = new Student(7,"测试7");
        Student s2 = new Student(2,"测试2");
        Student s3 = new Student(1,"测试1");
        Student s4 = new Student(5,"测试5");

        List<Student> list = new ArrayList<>();
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s4);

        //写法一
        list.sort((st,temp2) -> st.compareByNameInstance(temp2));

        //优化二
        list.sort(s1 :: compareByNameInstance1);

        list.forEach(student -> System.out.println(student.getName()));

    }
}

如果是调用实例方法时需要注意一个特征,抽象方法的第一个参数刚好是实例变量的类型。

构造器引用

暂时不去关注,没发现有啥用处。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值