编程语言
首页 > 编程语言> > Java基础之Lambda表达式

Java基础之Lambda表达式

作者:互联网

一、Lambda表达式的介绍

Lambda 表达式Java 8 发布的最重要新特性之一,lambda表达式本质上是一个匿名方法。它允许把函数作为一个方法的参数(函数作为参数传递进方法中)或者把代码看成数据。其优缺点主要有:

优点:
1、使用 Lambda 表达式可以使代码变的更加简洁紧凑;
2、非常容易并行计算;
3、可能代表未来的编程趋势;

缺点:
1、若不用并行计算,很多时候计算速度没有比传统的 for 循环快(CPU单核),并行计算有时需要预热才显示出效率优势;
2、不容易调试;
3、易读性较差,需了解过Lambda 表达式才能看懂;

使用场景
1、函数式接口都可以使用Lambda 表达式;
2、包含复杂数据结构及对象时,可配合Stream进行计算,转化等一系列操作;

Lambda表达式的构造形式:
在最简单的形式中,一个lambda可以参数列表(逗号分隔参数)、–>符号函数体三部分表示,例如:Predicate p = x ->Integer.parseInt(x)>5

Lambda表达式的表现形式:
在某些情况下lambda的函数体会比较复杂,这时可以把函数体放到在一对花括号中,就像在Java中定义普通函数一样。表达式可以引用类的成员变量与局部变量(这些变量会被隐含的转为final,目的为了更高的效率)。Lambda表达式式支持有返回值,返回值的类型可由编译器推测出来的,当然如果lambda的函数体只有一行的话,那么没有必要显式使用return语句;

二、函数式接口的介绍

简介:
要想很好地使用lambda表达式,就必须了解函数式接口的概念。函数式接口和普通接口并没有什么不同,唯一的区别在于其接口内部有且只有一个抽象的方法,且需要在接口加上注解(@FunctionalInterface,该注解表明其为函数式接口),像这类的接口就可以被隐式转换为lambda表达式,也就是函数式接口。在实际开发过程中,任何函数式接口都可以使用lambda表达式进行替换,例如:ActionListener、Comparator、Runnable等;

Jdk8常用函数接口:
目前Jdk8自定义的常用函数式接口有Function,Consumer、Supplier、Predicate四大类,其具体详解,可见下表:

接口名称参数用途
Function<T, R>入参T,出参R主要用于参数转化
Consumer<T>入参T,无出参主要用于循环迭代,类似于for循环
Supplier<T>无入参,出参T主要于生成特定的参数,包括对象,类似于构造函数
Predicate<T>入参T,出参boolean型主要用于条件判断,类似于if条件语句

Jdk8还有其它的函数式接口,但大多是以以上4大接口衍生而来,当然开发者也可以自己定义函数式接口,但定义函数式接口时,切记接口内部一定有且只有一个抽象方法,且需要加上@FunctionalInterface注解;

三、Lambda表达式的应用举例

3.1、类的静态方法
功能:将字符串整数数字转化整形数字

① 非函数引用

Function<String, Integer> oldFun = new Function<String, Integer>() {
            // 注意parseInt方法必须和apply方法的出入参数必须相同
            @Override
            public Integer apply(String s) {
                return Integer.parseInt(s);
            }
        };

说明:
以上是采用匿名内部类的形式;

② 函数引用

Function<String, Integer> newFun = Integer::parseInt;

说明:
函数引用,其中需要注意的是parseInt方法必须和apply方法的出入参数必须相同(类型),否则将会报错,请参照非函数引用进行理解;

3.2、类的非静态方法
功能:获取学生列表的姓名;

① 非函数引用

@Test
    public void test2() {
        List<Student> stuList = new ArrayList<>();
        stuList.add(new Student("夏侯惇", 31));
        stuList.add(new Student("不知火舞", 24));
        stuList.add(new Student("孙尚香", 27));
        stuList.add(new Student("曹操", 36));
        stuList.add(new Student("周瑜", 32));
        List<String> stuNameList = stuList.stream().map(new Function<Student, String>() {
            @Override
            public String apply(Student stu) {
                return stu.getName();
            }
        }).collect(Collectors.toList());
    }

说明:
以上是采用匿名内部类的形式,获取列表学生的姓名;

② 函数引用

@Test
    public void test2() {
        List<Student> stuList = new ArrayList<>();
        stuList.add(new Student("夏侯惇", 31));
        stuList.add(new Student("不知火舞", 24));
        stuList.add(new Student("孙尚香", 27));
        stuList.add(new Student("曹操", 36));
        stuList.add(new Student("周瑜", 32));
        // 非静态方法的函数引用(Student::getName)
        List<String> stuNameList = stuList.stream().map(Student::getName).collect(Collectors.toList());
    }

说明:
其中getName为Student类的非静态方法,针对非静态方法要使用函数引用,必须满足apply方法的入参为非静态方法的主调者且出参必须与apply方法保持一致(类型),请参照非函数引用进行理解;

3.3、对象引用
功能:获取学生的年龄;
① 非函数引用

@Test
    public void test3() {
        Student stu = new Student("夏侯惇", 31);
        // 非函数引用
        Optional<Integer> first = Stream.of(stu).map(new Function<Student, Integer>() {
            @Override
            public Integer apply(Student stu2) {
                return stu.get(stu2);
            }
        }).findFirst();
    }

说明:非函数引用Student对象的年龄;

② 函数引用
Student类的方法

 public Integer get(Student stu) {
        return stu.getAge();
    }
@Test
    public void test3() {
        Student stu = new Student("夏侯惇", 31);
        // apply方法与get方法的出入参数必须相同
        Optional<Integer> first = Stream.of(stu).map(stu::get).findFirst();
    }

说明
采用对象引用,但必须满足apply方法与get方法的出入参数相同(类型),请参照非函数引用进行理解;

标签:stuList,Java,函数,接口,Student,new,表达式,Lambda
来源: https://blog.csdn.net/qq_38098851/article/details/104013768