我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java新特性:Lambda表达式

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java新特性:Lambda表达式

Java新特性:Lambda表达式

Lambda 表达式(Lambda expression),也可称为闭包(Closure),是 Java(SE)8 中一个重要的新特性。Lambda 表达式允许我们通过表达式来代替功能接口。Lambda 表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块)

Lambda 表达式可以看作是一个匿名函数,基于数学中的 λ 演算得名。



1、Lambda表达式概述

1.1、Lambda表达式的简介

Lambda 表达式(Lambda expression),也可称为闭包(Closure),是 Java(SE)8 中一个重要的新特性。

Lambda 表达式允许我们通过表达式来代替功能接口。Lambda 表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块)

Lambda 表达式可以看作是一个匿名函数,基于数学中的 λ 演算得名。

1.2、Lambda表达式的语法

Lambda 表达式的基本语法:

(parameters) -> expression 或 (parameters) -> { statements; }

Lambda 表达式的三个组成部分:

image-20230707105839045

  1. 参数列表(parameters):类似方法中的形参列表,这里的参数是函数式接口里的参数。这里的参数类型可以明确的声明,也可不声明而由 JVM 隐含的推断。另外当只有一个推断类型时可以省略掉圆括号;
  2. 箭头(->):连接参数列表和 Lambda 主体,可理解为"被用于"的意思;
  3. Lambda 主体(expression 或 { statements; }):可以是表达式也可以代码块,是函数式接口里方法的实现。代码块可返回一个值或者什么都不反回,这里的代码块块等同于方法的方法体。如果是表达式,也可以返回一个值或者什么都不反回。

Lambda 表达式样例:

        // 1. 不需要参数,返回值为 2        () -> 2// 2. 接收一个参数(数字类型),返回其2倍的值        x -> 2*x// 3. 接受2个参数(数字),并返回他们的和        (x, y) -> x+y// 4. 接收2个int型整数,返回他们的乘积        (int x, int y) -> x*y// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)        (String s) -> System.out.print(s)
1.3、Lambda表达式的要求

虽然说,Lambda 表达式可以在⼀定程度上简化接口的实现。但是,并不是所有的接口都可以使用 Lambda 表达式来简洁实现的。

Lambda 表达式毕竟只是⼀个匿名方法。当实现的接口中的方法过多或者多少的时候,Lambda 表达式都是不适用的。

Lambda 表达式,只能实现函数式接口。


2、函数式接口

2.1、什么是函数式接口

如果说,⼀个接口中,要求实现类必须实现的抽象方法,有且只有⼀个!这样的接口,就是函数式接口。

代码如下(示例):

// 有且只有一个实现类必须要实现的抽象方法,所以是函数式接口interface Demo{    public void action();}

或者(示例):

// 有且只有一个实现类必须要实现的抽象方法,所以是函数式接口interface Demo{    public void action();    public default void action2() {        System.out.println("JDK1.8新特性,default默认方法可以有具体的实现");    }}
2.2、函数式接口注解(@FunctionalInterface)

在接口之前,我们可以使用 @FunctionalInterface 注解来判断这个接口是否是⼀个函数式接口。,用如果是函数式接口,没有任何问题。如果不是函数式接口,则会报错。功能类似于 @Override
代码如下(示例):

@FunctionalInterfaceinterface Demo{    public void action();}

3、Lambda表达式的使用

3.1、Lambda表达式的基本使用

例1(无参数无返回值):

@FunctionalInterfaceinterface NoParameterNoReturn {    // 注意:只能有一个抽象方法    void action();}public class TestDemo {    public static void main(String[] args) {        NoParameterNoReturn noParameterNoReturn = () -> {            System.out.println("无参数无返回值");        };        // action方法的主体内容在上述括号内        noParameterNoReturn.action();      }}

例2(一参数无返回值):

@FunctionalInterfaceinterface OneParameterNoReturn {  // 注意:只能有一个抽象方法    void action(int a);}public class TestDemo {    public static void main(String[] args) {        OneParameterNoReturn oneParameterNoReturn = (int a) -> {            System.out.println("一参数无返回值:" + "参数1:" + a);        };        // action方法的主体内容在上述括号内        oneParameterNoReturn.action(10);     }}

例3(多参数无返回值):

@FunctionalInterfaceinterface MoreParameterNoReturn {  // 注意:只能有一个抽象方法    void action(int a, int b);}public class TestDemo {    public static void main(String[] args) {MoreParameterNoReturn moreParameterNoReturn = (int a, int b) -> {            System.out.println("多参数无返回值:" + "参数1:" + a  + "参数2:" + b);        };        moreParameterNoReturn.action(20, 30);     }}

例4(无参数有返回值):

@FunctionalInterfaceinterface NoParameterReturn {    int action();}public class TestDemo {    public static void main(String[] args) {        NoParameterReturn noParameterReturn = () -> {            System.out.println("无参数有返回值");            return 40;        };        //接收函数的返回值        int ret = noParameterReturn.action();        System.out.println(ret);     }}

例5(一参数有返回值):

//有返回值一个参数@FunctionalInterfaceinterface OneParameterReturn {    int action(int a);}public class TestDemo {    public static void main(String[] args) {        OneParameterReturn oneParameterReturn = (int a) -> {            System.out.println("一参数有返回值");            return a;        };        ret = oneParameterReturn.action(50);        System.out.println(ret);     }}

例6(多参数有返回值):

@FunctionalInterfaceinterface MoreParameterReturn {    int action(int a, int b);} public class TestDemo {    public static void main(String[] args) {        MoreParameterReturn moreParameterReturn = (int a, int b) -> {            System.out.println("多参数有返回值");            return a + b;        };        ret = moreParameterReturn.action(60, 70);        System.out.println(ret);     }}
3.2、Lambda表达式的语法精简

Lambda 表达式的语法精简:

  • 参数类型可以省略,如果需要省略,每个参数的类型都要省略;
  • 参数的小括号里面只有一个参数,那么小括号可以省略;
  • 如果方法体当中只有一句代码,那么大括号可以省略;
  • 如果方法体中只有一条语句,其是 return 语句,那么大括号可以省略,且去掉 return 关键字。

4、变量捕获

Lambda 表达式中存在变量捕获,了解了变量捕获之后,我们才能更好的理解 Lambda 表达式的作用域。Java 当中的匿名类中,会存在变量捕获。

4.1、匿名内部类的变量捕获

所谓变量捕获就是:匿名内部类中访问所在方法或代码块中的局部变量,这个过程被称为 “变量捕获”。

public static void main(String[] args) {    // 变量捕获    int a = 100;    NoParameterNoReturn noParameterNoReturn = new NoParameterNoReturn() {        @Override        public void action() {            // 捕获a变量            System.out.println(a);           }    };    noParameterNoReturn.action();}结果:100

但是,只有在局部变量是 “有效的最终变量” 时,匿名内部类才能够引用它。如果局部变量不是有效的最终变量,则无法在匿名内部类中引用它,会导致编译错误。

有效的最终变量指的是一个在生命周期中没有被修改过的局部变量,它可以被认为是一个常量。

4.2、Lambda的变量捕获

同样的,Lambda 的变量捕获也是只有在局部变量是 “有效的最终变量” 时,才能够引用它。

public static void main(String[] args) {    // 变量捕获    int a = 100;    NoParameterNoReturn noParameterNoReturn = ()->{        // 捕获a变量        System.out.println(a);    };    noParameterNoReturn.action();}结果:100
4.3、匿名内部类的变量捕获与Lambda的变量捕获的区别

区别:Lambda 表达式可以捕获外面的 this,而匿名内部类无法直接捕获外面的 this。

在 Lambda 表达式中,this 关键字引用的是 Lambda 表达式所在的类的实例,而不是 Lambda 表达式内部的类的实例。这个特性被称为 “闭包”。

匿名内部类中的 this 关键字引用的是匿名内部类的实例,而不是外部类的实例。

public class Student {    // 外部类的属性    String name = "Student";    int age;     NoParameterNoReturn noParameterNoReturn = new NoParameterNoReturn() {        // 内部类自己的属性        String name = "hello";        @Override        public void action() {            System.out.println(this.name);        }    };     NoParameterNoReturn noParameterNoReturn2 = ()->{        String name = "hello";        System.out.println(this.name);    };     public static void main(String[] args) {        Student student = new Student();      // 结果:hello        student.noParameterNoReturn.action();      // 结果:Student        student.noParameterNoReturn2.action();    }}

如果想让匿名内部类的捕获外面的 this,就需要使用外部类的类名或对象引用来访问。

public class Student {    // 外部类的属性    String name = "Student";    int age;      NoParameterNoReturn noParameterNoReturn = new NoParameterNoReturn() {        // 内部类自己的属性        String name = "hello";        @Override        public void action() {            System.out.println(Student.this.name);        }    };}结果:Student

5、Lambda 在集合当中的使用

为了能够让 Lambda 和 Java 的集合类集更好的一起使用,集合当中,也新增了部分接口,以便与 Lambda 表达式对接。

对应的接口新增的方法
CollectionforEach() removeIf() spliterator() stream() parallelStream()
ListreplaceAll() sort()
MapgetOrDefault() forEach() replaceAll() putIfAbsent() remove() replace() computeIfAbsent() computeIfPresent() compute() merge()
5.1、Collection接口中的forEach()方法

这个方法是在接口 Iterable 当中的:

    default void forEach(Consumer action) {        Objects.requireNonNull(action);        for (T t : this) {            action.accept(t);        }    }

这个方法表示用于对集合中的每个元素执行指定的操作。

java复制代码public class Test {    public static void main(String[] args) {        List list = new ArrayList<>();        list.add("Hello");        list.add("bit");        list.add("hello");        list.add("lambda");                // Lambda 遍历 list        list.forEach((String s)->{            System.out.println(s);        });            // 简化      // list.forEach(s -> System.out.println(s));    }}结果:Hello bit hello lambda
5.2、List接口中的sort()方法

List 接口中的 sort() 方法:

    default void sort(Comparator c) {        Object[] a = this.toArray();        Arrays.sort(a, (Comparator) c);        ListIterator i = this.listIterator();        for (Object e : a) {            i.next();            i.set((E) e);        }    }

该方法根据 c 指定的比较规则对容器元素进行排序。可以看到其参数是 Comparator,我们点进去看下:又是一个函数式接口:

@FunctionalInterfacepublic interface Comparator {...    int compare(T o1, T o2);    ...}

使用示例:

public class TestDemo2 {    public static void main(String[] args) {        ArrayList list = new ArrayList<>();        list.add("Hello");        list.add("bit");        list.add("hello");        list.add("lambda");                list.sort(new Comparator() {            @Override            public int compare(String o1, String o2) {                return o1.length() - o2.length();            }        });                list.forEach(s -> System.out.println(s));    }}输出结果为:bit Hello hello lambda

修改为 Lambda 表达式:

public class TestDemo2 {    public static void main(String[] args) {        ArrayList list = new ArrayList<>();        list.add("Hello");        list.add("bit");        list.add("hello");        list.add("lambda");        // 对list集合中的字符串按照长度进行排序        list.sort((o1, o2) -> o1.length() - o2.length());        list.forEach(s -> System.out.println(s));    }}输出结果为:bit Hello hello lambda
5.3、Map接口的forEach()方法

HashMap 的 forEach() 方法:

    default void forEach(BiConsumer action) {        Objects.requireNonNull(action);        for (Map.Entry entry : entrySet()) {            K k;            V v;            try {                k = entry.getKey();                v = entry.getValue();            } catch(IllegalStateException ise) {                // this usually means the entry is no longer in the map.                throw new ConcurrentModificationException(ise);            }            action.accept(k, v);        }    }

可以看到这个方法有一个 BigConsumer,并且这也是一个函数式接口:

@FunctionalInterfacepublic interface BiConsumer {...    void accept(T t, U u);    ...}

代码示例:

public class TestDemo2 {    public static void main(String[] args) {        HashMap map = new HashMap<>();        map.put(1, "hello");        map.put(2, "bit");        map.put(3, "hello");        map.put(4, "lambda");        map.forEach(new BiConsumer() {            @Override            public void accept(Integer integer, String string) {                System.out.println(integer + " " + string);            }        });    }}输出结果:1 hello2 bit3 hello4 lambda

修改为 Lambda 表达式:

public class TestDemo2 {    public static void main(String[] args) {        HashMap map = new HashMap<>();        map.put(1, "hello");        map.put(2, "bit");        map.put(3, "hello");        map.put(4, "lambda");        map.forEach((integer, string) ->                System.out.println(integer + " " + string)        );    }}

来源地址:https://blog.csdn.net/weixin_45187434/article/details/131622541

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java新特性:Lambda表达式

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Java新特性:Lambda表达式

Java新特性:Lambda表达式 Lambda 表达式(Lambda expression),也可称为闭包(Closure),是 Java(SE)8 中一个重要的新特性。Lambda 表达式允许我们通过表达式来代替功能接口。Lambd
2023-08-17

Java8新特性-Lambda表达式详解

Java8(又称为jdk1.8)是Java语言开发的一个主要版本。Lambda表达式,也可称为闭包,它是推动Java8发布的最重要新特性。本文通过详细的代码示例介绍了Java8新特性感兴趣的朋友可以参考一下
2023-05-16

java8新特性lambda表达式的语法是什么

这篇“java8新特性lambda表达式的语法是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“java8新特性lambd
2023-07-05

java8新特性-lambda表达式入门学习心得

这篇文章主要介绍了java8新特性-lambda表达式入门学习心得,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-03-13

java lambda表达式有哪些特点

Java lambda表达式有以下特点:1. 简洁性:使用lambda表达式可以更简洁地表示匿名函数,减少了冗余代码。2. 函数式编程:lambda表达式使得Java可以支持函数式编程,可以将函数作为参数传递给其他函数,或者将函数作为返回值
2023-10-10

Java8新特性Lambda表达式的一些复杂用法总结

简介lambda表达式是JAVA8中提供的一种新的特性,它支持Java也能进行简单的“函数式编程”。 它是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一
2023-05-31

Java中Lambda表达式和函数式接口的使用和特性

JavaLambda表达式是一种函数式编程的特性,可简化匿名内部类的写法,与函数式接口搭配使用,实现代码简洁、可读性高、易于维护的特点,适用于集合操作、多线程编程等场景
2023-05-16

Java8中函数式接口与Lambda表达式的特性

今天就跟大家聊聊有关Java8中函数式接口与Lambda表达式的特性,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。什么是Lambda表达式,java8为什么使用Lambda表达式?“
2023-05-31

java lambda表达式的语法特点有哪些

Java lambda表达式的语法特点包括以下几点:1. 简洁:lambda表达式可以以更简洁的方式表示匿名函数。2. 参数列表:lambda表达式可以包含零个或多个参数,参数类型可以根据上下文自动推断。3. 箭头运算符:箭头运算符"->"
2023-09-23

Java Lambda表达式怎么应用

Java 中的 Lambda 表达式是 JDK 8 中引入的一种函数式编程的特性,它可以使代码更简洁、更易读、更易维护。Lambda 表达式适用于需要使用函数式接口的地方,函数式接口是只有一个抽象方法的接口。Lambda 表达式的基本语法如
2023-10-10

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录