​Lambda表达式详解​-初遇者-很细

news2024/12/24 11:45:15

目录

Lambda简介

对接口的要求

Lambda 基础语法

Lambda 语法简化

Lambda 表达式常用示例

lambda 表达式引用方法

构造方法的引用

lambda 表达式创建线程

遍历集合

删除集合中的某个元素

集合内元素的排序

Lambda 表达式中的闭包问题


Lambda简介

Lambda 表达式是 JDK8 的一个新特性,可以取代大部分的匿名内部类,写出更优雅的 Java 代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代码结构。

JDK 也提供了大量的内置函数式接口供我们使用,使得 Lambda 表达式的运用更加方便、高效。

对接口的要求

虽然使用 Lambda 表达式可以对某些接口进行简单的实现,但并不是所有的接口都可以使用 Lambda 表达式来实现。Lambda 规定接口中只能有一个需要被实现的方法,不是规定接口中只能有一个方法

jdk 8 中有另一个新特性:default, 被 default 修饰的方法会有默认实现,不是必须被实现的方法,所以不影响 Lambda 表达式的使用。

@FunctionalInterface

修饰函数式接口的,要求接口中的抽象方法只有一个。 这个注解往往会和 lambda 表达式一起出现。

Lambda 基础语法

我们这里给出六个接口,后文的全部操作都利用这六个接口来进行阐述。

/**多参数无返回*/

@FunctionalInterface
public interface NoReturnMultiParam {
    void method(int a, int b);
}

/**无参无返回值*/

@FunctionalInterface
public interface NoReturnNoParam {
    void method();
}

/**一个参数无返回*/

@FunctionalInterface
public interface NoReturnOneParam {
    void method(int a);
}

/**多个参数有返回值*/

@FunctionalInterface
public interface ReturnMultiParam {
    int method(int a, int b);
}


/*** 无参有返回*/
@FunctionalInterface
public interface ReturnNoParam {
    int method();
}

/**一个参数有返回值*/
@FunctionalInterface
public interface ReturnOneParam {
    int method(int a);
}

语法形式为 () -> {},其中 () 用来描述参数列表,{} 用来描述方法体,-> 为 lambda运算符 ,读作(goes to)。

import lambda.interfaces.*;
public class Test1 {

    public static void main(String[] args) {

        //无参无返回 定义
        NoReturnNoParam noReturnNoParam = () -> {
            System.out.println("NoReturnNoParam");
        };

        //调用
        noReturnNoParam.method();

        //一个参数无返回
        NoReturnOneParam noReturnOneParam = (int a) -> {
            System.out.println("NoReturnOneParam param:" + a);
        };
        noReturnOneParam.method(6);

        //多个参数无返回
        NoReturnMultiParam noReturnMultiParam = (int a, int b) -> {
            System.out.println("NoReturnMultiParam param:" + "{" + a +"," + + b +"}");
        };
        noReturnMultiParam.method(6, 8);

        //无参有返回值
        ReturnNoParam returnNoParam = () -> {
            System.out.print("ReturnNoParam");
            return 1;
        };
        int res = returnNoParam.method();
        System.out.println("return:" + res);

        //一个参数有返回值
        ReturnOneParam returnOneParam = (int a) -> {
            System.out.println("ReturnOneParam param:" + a);
            return 1;
        };
        int res2 = returnOneParam.method(6);
        System.out.println("return:" + res2);

        //多个参数有返回值
        ReturnMultiParam returnMultiParam = (int a, int b) -> {
            System.out.println("ReturnMultiParam param:" + "{" + a + "," + b +"}");
            return 1;
        };
        int res3 = returnMultiParam.method(6, 8);
        System.out.println("return:" + res3);
    }

}

Lambda 语法简化

我们可以通过观察以下代码来完成代码的进一步简化,写出更加优雅的代码。

import lambda.interfaces.*;
public class Test2 {

    public static void main(String[] args) {

        //1.简化参数类型,可以不写参数类型,但是必须所有参数都不写
        NoReturnMultiParam lamdba1 = (a, b) -> {
            System.out.println("简化参数类型");
        };
        lamdba1.method(1, 2);

        //2.简化参数小括号,如果只有一个参数则可以省略参数小括号
        NoReturnOneParam lambda2 = a -> {
            System.out.println("简化参数小括号");
        };
        lambda2.method(1);

        //3.简化方法体大括号,如果方法条只有一条语句,则可以省略方法体大括号
        NoReturnNoParam lambda3 = () -> System.out.println("简化方法体大括号");
        lambda3.method();

        //4.如果方法体只有一条语句,并且是 return 语句,则可以省略方法体大括号
        ReturnOneParam lambda4 = a -> a+3;
        System.out.println(lambda4.method(5));
        ReturnMultiParam lambda5 = (a, b) -> a+b;
        System.out.println(lambda5.method(1, 1));

    }

}


 

Lambda 表达式常用示例

lambda 表达式引用方法

有时候我们不是必须要自己重写某个匿名内部类的方法,我们可以可以利用 lambda表达式的接口快速指向一个已经被实现的方法。

语法

方法归属者::方法名 静态方法的归属者为类名,普通方法归属者为对象

public class Exe1 {

    public static void main(String[] args) {

        ReturnOneParam lambda1 = a -> doubleNum(a);
        System.out.println(lambda1.method(3));

        //lambda2 引用了已经实现的 doubleNum 方法
        ReturnOneParam lambda2 = Exe1::doubleNum;
        System.out.println(lambda2.method(3));

        Exe1 exe = new Exe1();
        //lambda4 引用了已经实现的 addTwo 方法
        ReturnOneParam lambda4 = exe::addTwo;
        System.out.println(lambda4.method(2));

    }

    /**
     * 要求
     * 1.参数数量和类型要与接口中定义的一致
     * 2.返回值类型要与接口中定义的一致
     */

    public static int doubleNum(int a) {
        return a * 2;
    }

    public int addTwo(int a) {
        return a + 2;
    }

}

构造方法的引用

一般我们需要声明接口,该接口作为对象的生成器,通过 类名::new 的方式来实例化对象,然后调用方法返回对象。

interface ItemCreatorBlankConstruct {
    Item getItem();
}

interface ItemCreatorParamContruct {
    Item getItem(int id, String name, double price);
}

public class Exe2 {

    public static void main(String[] args) {
        ItemCreatorBlankConstruct creator = () -> new Item();
        Item item = creator.getItem();

        ItemCreatorBlankConstruct creator2 = Item::new;
        Item item2 = creator2.getItem();

        ItemCreatorParamContruct creator3 = Item::new;
        Item item3 = creator3.getItem(112, "鼠标", 135.99);
    }

}

lambda 表达式创建线程

我们以往都是通过创建 Thread 对象,然后通过匿名内部类重写 run() 方法,一提到匿名内部类我们就应该想到可以使用 lambda 表达式来简化线程的创建过程。

    Thread thread=new Thread( new Runnable() {
           @Override
           public void run() {

           }
    });

     //简化后
    Thread t = new Thread(() -> {
      for (int i = 0; i < 10; i++) {
        System.out.println(2 + ":" + i);
      }
    });

     t.start();

遍历集合

我们可以调用集合的 public void forEach(Consumer<? super E> action) 方法,通过 lambda 表达式的方式遍历集合中的元素。以下是 Consumer 接口的方法以及遍历集合的操作。Consumer 接口是 jdk 为我们提供的一个函数式接口。

    @FunctionalInterface
    public interface Consumer<T> {
        void accept(T t);
        //....
    }

      ArrayList<Integer> list = new ArrayList<>();
      Collections.addAll(list, 1,2,3,4,5);

      //lambda表达式 方法引用
      list.forEach(System.out::println);
      list.forEach(element -> {
        if (element % 2 == 0) {
          System.out.println(element);
        }

      });

删除集合中的某个元素

我们通过public boolean removeIf(Predicate<? super E> filter)方法来删除集合中的某个元素,Predicate 也是 jdk 为我们提供的一个函数式接口,可以简化程序的编写。

      ArrayList<Item> items = new ArrayList<>();
      items.add(new Item(11, "小牙刷", 12.05 ));
      items.add(new Item(5, "日本马桶盖", 999.05 ));
      items.add(new Item(7, "格力空调", 888.88 ));
      items.add(new Item(17, "肥皂", 2.00 ));
      items.add(new Item(9, "冰箱", 4200.00 ));
      items.removeIf(ele -> ele.getId() == 7);

      //通过 foreach 遍历,查看是否已经删除
      items.forEach(System.out::println);

集合内元素的排序

在以前我们若要为集合内的元素排序,就必须调用 sort 方法,传入比较器匿名内部类重写 compare 方法,我们现在可以使用 lambda 表达式来简化代码。

        ArrayList<Item> list = new ArrayList<>();
        list.add(new Item(13, "背心", 7.80));
        list.add(new Item(11, "半袖", 37.80));
        list.add(new Item(14, "风衣", 139.80));
        list.add(new Item(12, "秋裤", 55.33));

        //通常写法

        /*
        list.sort(new Comparator<Item>() {
            @Override
            public int compare(Item o1, Item o2) {
                return o1.getId()  - o2.getId();
            }
        });

        */

        //简化写法
        list.sort((o1, o2) -> o1.getId() - o2.getId());
        System.out.println(list);

Lambda 表达式中的闭包问题

这个问题我们在匿名内部类中也会存在,如果我们把下例注释放开会报错,告诉我 num 值是 final 不能被改变。这里我们虽然没有标识 num 类型为 final,但是在编译期间虚拟机会帮我们加上 final 修饰关键字。

import java.util.function.Consumer;
public class Main {

    public static void main(String[] args) {
        int num = 10;
        Consumer<String> consumer = ele -> {
            System.out.println(num);
        };
        //num = num + 2;
        consumer.accept("hello");
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/572016.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

骑行,为日益冷漠的人际关系加点温度

随着社会的发展和人们生活水平的提高&#xff0c;越来越多的年轻人、老年人和中年人开始关注健康和运动。而骑行作为一种健康、环保、经济实惠的运动方式&#xff0c;受到越来越多人的喜爱。本文将从社会面探讨这些话题对于不同人群的影响。 首先&#xff0c;骑行对身体有着多方…

狂飙,从功能测试转到自动化测试,我的测试之路涨了20k...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 Python自动化测试&…

《四》Git 中的远程仓库

SSH 登录&#xff1a; 每个远程仓库都有两种地址&#xff1a;HTTPS 和 SSH。如果是 HTTPS 的地址&#xff0c;每次 push 的时候都要输入用户名和密码以校验身份。如果 SSH 的方式&#xff0c;就不再需要每次都输入用户名和密码了。 cd ~ 进入用户的家目录&#xff0c;执行 ss…

ChatGPT在智能外呼机器人领域的应用

随着人工智能技术的不断发展&#xff0c;自然语言处理(NLP)技术也逐渐成为各行各业的热门技术。其中&#xff0c;ChatGPT技术是近年来备受关注的技术之一。ChatGPT技术是一种基于自然语言处理和深度学习的人工智能技术&#xff0c;它可以处理自然语言文本&#xff0c;实现自动化…

Maven 概述及下载安装

一、为什么要学习 Maven 我们构建一个项目需要用到很多第三方的类库&#xff0c;就需要引入大量的jar包&#xff0c;并且Jar包之间的关系错综复杂&#xff0c;缺少任何一个Jar包都会导致项目编译失败。Maven 能帮助我们下载及管理依赖。 本地项目代码开发完成后&#xff0c;我…

如何在华为OD机试中获得满分?Java实现【字母组合】一文详解

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: Java华为OD机试真题&#xff08;2022&2023) 文章目录 1. 题目描述2. 输入描述3. 输出描述…

Android:如何从源码编译OpenCV4Android库

原文摘自知乎网友稚晖的文章《如何从源码编译OpenCV4Android库》 https://blog.csdn.net/LateLinux/article/details/111149544 我在这里根据自己的经验&#xff0c;增加一些备注。 1.需要的工具和源码&#xff1a; opencv4.1&#xff08;opencv4.6也可以编译通过&#xff09…

跟随林曦,做自己的“生活家”

时代在以加速度的方式变化&#xff0c;让人难以从容。而当我们陷于横向的比较系统&#xff0c;权衡着卷、躺时&#xff0c;也有人在探寻另一条纵向的路——向古人学习&#xff0c;以传统美学关照和滋养当下生活。      立夏之际&#xff0c;水墨画家林曦的新作《无用之美》…

数据结构【链表】看完还怕拿不下链表?

✨Blog&#xff1a;&#x1f970;不会敲代码的小张:)&#x1f970; &#x1f251;推荐专栏&#xff1a;C语言&#x1f92a;、Cpp&#x1f636;‍&#x1f32b;️、数据结构初阶&#x1f480; &#x1f4bd;座右铭&#xff1a;“記住&#xff0c;每一天都是一個新的開始&#x1…

推荐5款提高生活和工作效率的好帮手

在这个数字化时代,软件工具已经深深地影响和改变了我们的生活和工作。有着各种各样的软件工具,它们都可以在特定的领域内让我们变得更加高效,完成复杂的任务。选择一款适合你的软件工具,不但可以极大地释放生产力,也可以让生活变得更加便捷。 1.桌面图标管理工具——TileIconi…

阿里开源!集成了 AIGC 的免费数据库工具:Chat2DB

今天推荐的这个项目是「Chat2DB」&#xff0c;一款开源免费的数据库客户端工具&#xff0c;支持 Windows、Mac 本地安装&#xff0c;也支持服务器端部署&#xff0c;Web 网页访问。 和传统的数据库客户端软件 Navicat、DBeaver 相比 Chat2DB 集成了 AIGC 的能力&#xff0c;能…

基于LLMs的多模态大模型(PALM-E,ArtGPT-4,VPGTrans )

这个系列已经更文一些了&#xff0c;如果有新的文章会继续补充&#xff1a; 基于LLMs的多模态大模型&#xff08;Visual ChatGPT&#xff0c;PICa&#xff0c;MM-REACT&#xff0c;MAGIC&#xff09;基于LLMs的多模态大模型&#xff08;Flamingo, BLIP-2&#xff0c;KOSMOS-1&…

2023年DAMA-CDGA/CDGP认证合肥/厦门/长春/深圳可以报名

DAMA认证为数据管理专业人士提供职业目标晋升规划&#xff0c;彰显了职业发展里程碑及发展阶梯定义&#xff0c;帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力&#xff0c;促进开展工作实践应用及实际问题解决&#xff0c;形成企业所需的新数字经济下的核心职业…

【MySQL】实验十 E-R图

文章目录 1. 学校2. 院系3. 图书馆4. 舰队5. 工厂6. 网购7. 公司1. 学校 设有如下实体: 班主任:工号、姓名、电话 班级:班号、专业、毕业总学分 学生:学号、姓名、性别、年龄 课程:课程号、课程名 上述实体中存在如下联系: (1)一个班主任管理一个班级,一个班级由一个…

小兔鲜--项目总结 2

目录 登录-表单校验实现 表单如何进行校验 表单校验步骤 自定义校验规则 整个表单的内容验证 登录-基础登录业务实现 登录业务流程 Pinia管理用户数据 如何使用Pinia管理数据 关键代码总结 登录-Pinia用户数据持久化 持久化用户数据说明 ​编辑关键步骤总结和插件运行机…

基于 JMeter 实现 WEB 项目性能测试,环境搭建与测试用例编写

目录 前言&#xff1a; 一、JDK 安装 二、Tomcat 安装 三、Redis 安装 四、数据库安装 五、WEB 项目搭建 六、性能测试项目搭建 七、总结 前言&#xff1a; 性能测试是软件开发中必不可少的一环&#xff0c;它可以帮助开发者提高程序的稳定性&#xff0c;优化性能&…

【产品经理】产品体验报告的思路

&#xff08;一&#xff09;产品概述 &#xff08;1&#xff09;体验环境 对于app来说&#xff0c;无非就是体验产品所用的机型&#xff0c;系统&#xff0c;然后app版本&#xff0c;体验时间&#xff0c;体验人等方面的信息。 &#xff08;2&#xff09;产品的概括或简介说…

基于LLMs的多模态大模型(Visual ChatGPT,PICa,MM-REACT,MAGIC)

当LLMs已经拥有了极强的对话能力后&#xff0c;如何使其拥有视觉和语音等多模态能力是紧接而来的热点&#xff08;虽然GPT4已经有了&#xff09;&#xff0c;这个系列将不定期更新一些利用LLMs做多模态任务的文章。 直觉上&#xff0c;如果直接训练一个类似chatgpt架构的多模态…

7种PCB走线方式

01电源布局布线相关 数字电路很多时候需要的电流是不连续的&#xff0c;所以对一些高速器件就会产生浪涌电流。 如果电源走线很长&#xff0c;则由于浪涌电流的存在进而会导致高频噪声&#xff0c;而此高频噪声会引入到其他信号中去。 而在高速电路中必然会存在寄生电感和寄…

SSM 如何使用 ShardingSphere 实现数据库分库分表

SSM 如何使用 ShardingSphere 实现数据库分库分表 简介 在大规模数据应用场景下&#xff0c;单一数据库可能无法承载高并发的读写操作。为了解决这个问题&#xff0c;一种常见的方式是使用数据库分库分表技术。ShardingSphere 是一个支持多种关系型数据库的分布式数据库中间件…