【Java学习笔记】9.5 Java中的Lambda表达式

news2024/11/26 8:21:56

Lambda表达式是从Java8版本开始增加的语法。Lambda表达式有利于实现函数式编程,简化开发。

9.5.1 Lambda表达式入门

Lambda表达式由三部分组成:参数列表、箭头(->),及一个表达式或语句块。其完整的语法格式如下:

(Type 1 param1 , Type 2 param2 , ... , Type N paramN , -> {
   statment1;
   		statment2;
   		// ........
   		return statmentM;
})

例如,对于以下方法:

public int add(int x,int y){
return x +y; 
}

可以改写成Lambda表达式:

(int x,int y) -> {return x+y};

Lambda表达式的特点是书写简练。下面几种语法是对他的简化。

  1. 单语句写法 当Lambda表达式只包含一条语句时,可以省略大括号、return和语句结尾的分号 (int x ,int y ) -> x + y

  2. 省略参数类型 Java是一个强类型语言,因此参数必须指定类型。但是如果编译器能够根据上下文推出Lambda表达式的参数类型,则不需要我们显示的指定参数类型。例如(x,y) - > x+y;

  3. 单个参数 如果只有一个参数并可以被Java推断出类型,那么参数列表的括号也可以省略。例如c -> {return c.size();}

  4. 无参数和返回值可以用Lambda表达式实现一个没有参数且返回值类型为void的方法。这时候的参数列表的括号不能省。例如() ->{System.out.println("Hello World");}

    Lambda表达式的返回值类型无需指定,编译器会自行判断。另外,Lambda表达式的参数可以使用修饰符及注解,如final、@NonNull等。
    Lambda表达式可以看做一个行为,利用Lambda表达式Java允许将行为传到函数里。在这之前,如果想将行为传入函数,仅有的选则就是使用匿名类。匿名类的定义较为啰嗦。有时会显得其中行为定义不够突出。
    Lambda表达式取代了匿名类,取消了模板。允许用函数式风格编写代码。这样有时可读性更好、表达更清晰。

9.5.2 Lambda表达式与函数式接口

函数式接口是Java为支持Lambda表达式引入的概念。函数式接口(Functional Interface,功能性接口),简单来说,是指仅包含一个方法的接口。Java标准库中的java.lang.Runnable和java.util.Comparator都是典型的函数式接口。

@FunctionalInterface
public interface Runnable{
public abstract void run();
}

@FunctionalInterface 是java提供的注解。这个注解是非必须的。只要接口符合函数式接口的标准(只包含一个方法的接口),虚拟机会自动进行判断。
但最好还是声明一下。防止团队其他成员再往接口里添加新的方法。

Java中的Lambda表达式无法单独出现,它需要传递给一个函数式接口。Lambda表达式的方法其实就是函数接口方法的实现。例如:
可以用一个Lambda表达式为一个函数式接口赋值。

Runnable r1 = () -> {System.out.println("Hello Lambda!");};

然后再赋值给一个Object

Object obj = r1;

一个Lambda表达式只有在显式的转换成一个函数式接口后才能被当做Object使用。

Object o = (Runnable)() - > { System.out.println("hi");}; //正确
---------------------------------------------------------------------------------
System.out.println(() ->{}); //正确

【实例1】创建一个叫ISay的函数式接口

  1. 函数式接口
package lambda;

@FunctionalInterface 				//函数式接口注解
public interface ISay {				//自定义函数式接口
	public void say(String str);    //唯一的接口方法
}
  1. 测试类
public class TestLambda {

	public static void main(String[] args) {
		//用Lambda函数实现了函数式接口中的方法
		ISay saysth = (String str) -> {System.out.println("You said:\""+str+"\"");};
		saysth.say("Hello World");	//调用已实现的接口方法
	}
}

在这里插入图片描述

TestLambda类没有实现接口ISay的代码,所以也不需要显示地实现say()方法。从而也没有专门实例化一个TestLambda类对象来调用其say()方法
如果不使用Lambda表达式,那么上述代码应该改写成如下形式:

public class TestLambda implements ISay{
	public static void main(String[] args){
		//实例化类并调用方法
		new TestLambda().say("Hello World");
	}
	@Override
	public void say(String str ){
	System.out.println("you said :\""+str+"\"");
}
}

9.5.3 方法引用与构造器引用

方法引用(Method References)也是从Java8版本开始增加的特性。书写形式:

类名::方法名

有时候Lambda表达式中花括号部分代码较多。这时可以把花括号中的代码写成一个有方法名的方法,然后在Lambda表达式中使用方法调用的形式。
【实例2】静态方法引用形式

package lambdaTest1;

import java.text.SimpleDateFormat;
import java.util.Date;

import lambda.ISay;

public class TestLambda2 {

	public static void main(String[] args) {
		//用Lambda函数实现了函数式接口中的方法
		// ISay saysth = (String str) -> {System.out.println("You said:\""+str+"\"");};
		ISay saysth = (String str) -> {
			TestLambda2.FormatWords(str);		//调用了FormatWords()方法
			};
			saysth.say("Hello World");			//调用接口方法
	}
	
	public static void FormatWords(String str) {//定义一个格式输出的静态方法
		//设置时间
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println(df.format(new Date())); //输出时间
		System.out.println("You Said:\""+str+"\"");	
	}
}

在这里插入图片描述
10 ~ 12 行,可替换为

ISay saysth = TestLambda2:FormatWords

在这里插入图片描述

类型示例
引用静态方法ContainingClass::staticMethodName
引用某个对象的实例方法ContainingObject::instanceMethodName
引用特定类型的任意对象方法ContainingType::methodName
引用构造方法(构造器引用)ClassName::new

【实例2】方法引用
Puppy.java

package example;

import java.time.LocalDate;

public class Puppy {
	public Puppy(String name,LocalDate birthday) {
		this.name = name;
		this.birthday = birthday;
	}
	String name;
	LocalDate birthday;
	
	public String getName() {
		return name;
	}
	
	public LocalDate gerBirthday() {
		return birthday;
	}
	
	//定义一个静态方法,比较两只狗的静态年龄
	
	public static int compareByAge(Puppy a , Puppy b) {
		return a.birthday.compareTo(b.birthday);
	}
	@Override
	public String toString() {
		return "Puppy["+ "name=" + name + ",birthday="+birthday+"+\n]";
	}
}

SortPuppy.java

package example;

import java.time.LocalDate;

public class Puppy {
	public Puppy(String name,LocalDate birthday) {
		this.name = name;
		this.birthday = birthday;
	}
	String name;
	LocalDate birthday;
	
	public String getName() {
		return name;
	}
	
	public LocalDate gerBirthday() {
		return birthday;
	}
	
	//定义一个静态方法,比较两只狗的静态年龄
	
	public static int compareByAge(Puppy a , Puppy b) {
		return a.birthday.compareTo(b.birthday);
	}
	@Override
	public String toString() {
		return "Puppy["+ "name=" + name + ",birthday="+birthday+"+\n]";
	}
}

接下来是一个引用特定类型的任意对象方法的例子。

package example;

import java.util.Arrays;

public class SortString {

	public static void main(String[] args) {
		String[] stringArray = {"Cocker","Akita","Beagle","Alaskan","Dachshund"};
		Arrays.sort(stringArray,String::compartTo);
		System.out.println(Arrays.asList(stringArray));
		}
}

【实例3】构造器引用
构造器引用也是一种方法引用,其引用的是构造方法。构造器引用只需要以new关键字作为引用名。格式:类名:new

IBirth.java

package IBirth;

import java.time.LocalDate;

import example.Puppy;

@FunctionalInterface
interface IBirth {
	Puppy born(String name , LocalDate birthday);
}

PuppyBirth.java

package IBirth;

import java.time.LocalDate;

import example.Puppy;

public class PuppyBirth {

	public static void main(String[] args) {
		
		IBirth puppy1 = (name,birthday)->new Puppy("Akita",LocalDate.of(2017,5,9));
		IBirth puppy2 = Puppy::new;

		System.out.println(puppy1.born("Akita", LocalDate.of(2017,5,9)));
		System.out.println(puppy2.born("Beagle", LocalDate.of(2016,5,9)));
	}

}

在这里插入图片描述

9.5.4 Lambda表达式与匿名内部类的练习和区别

Lambda表达式是匿名内部类的一种简化,因此他可以取代匿名内部类的作用。

  • 相同点
    (1)Java中局部内部类和匿名内部类访问的局部变量必须由final修饰。匿名内部类和Lambda表达式一样,可以访问final的局部变量和外部类成员变量
    (2) 创建方法一样,都可以直接调用从接口中继承的默认方法

    • 不同点
      (1)匿名内部类可以为任意接口创建实例——不管有多少个抽象的方法,只要匿名内部类实现了所有的方法即可。但是Lambda表达式只能为函数式接口创建实例
      (2)匿名内部类可以为抽象类甚至普通类创建实例。但是Lambda表达式只能为函数式接口创建实例
      (3)匿名内部类实现的抽象方法体允许调用接口中的默认方法,但Lambda表达式的代码不允许调用接口中的默认方法

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

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

相关文章

软考133-上午题-【软件工程】-软件项目估算

一、COCOMO 估算模型 COCOMO 模型是一种精确的、易于使用的成本估算模型。 COCOMO 模型按其详细程度分为:基本 COCOMO 模型、中级 COCOMO 模型和详细 COCOMO 模型。 1)基本 COCOMO 模型 基本 COCOMO 模型是一个静态单变量模型,用于对整个软…

Java基础 - 10 - IO流(二)

一. IO流 - 字符流 1.1 FileReader(文件字符输入流) 作用:以内存为基准,可以把文件中的数据以字符的形式读入到内存中去 构造器说明public FileReader(File file)创建字符输入流管道与源文件接通public FileReader(String pathn…

java:基于TCP协议的网络聊天室

基于TCP协议的网络聊天室 简单用java写了一个基于TCP协议的网络聊天室 基本功能 多用户同时在线聊天 收到消息时服务端会向所有在线用户群发消息 用户加入连接和断开连接时会提示 服务端 Socket socket;ArrayList<Socket> list;public ServerThread(Socket socket,…

使用Docker,【快速】搭建个人博客【WordPress】

目录 1.安装Mysql&#xff0c;创建&#xff08;WordPress&#xff09;用的数据库 1.1.安装 1.2.创建数据库 2.安装Docker 3.安装WodPress&#xff08;使用Docker&#xff09; 3.1.创建文件夹 3.2.查看镜像 3.3.获取镜像 3.4.查看我的镜像 3.5.使用下载的镜像&#xf…

产品创新领域中的生产率:以新产品销售额与研发支出的关系为视角

一、摘要 在当今日新月异的商业环境中&#xff0c;产品创新已成为企业获取竞争优势、实现持续增长的关键因素。而如何衡量产品创新的成效&#xff0c;即产品创新的生产率&#xff0c;则是众多企业所关注的焦点。本文将探讨产品创新领域中的生产率概念&#xff0c;并以新产品销…

Windows的Tensorrt的安装

Tensorrt的下载 确定自己的CUDA版本,匹配的去下载Tensorrt。 Tensorrt的下载 下载完成之后,直接解压到文件夹即可。 环境变量配置 最重要的一部就是环境变量的配置。 官方的安装指导文件给出了两种方法: (1)要么直接将/lib 添加到环境变量 PATH 中 (诶,windows没有LD_L…

时序预测 | Transformer时间序列预测 Matlab代码

文章目录 效果一览文章概述源码设计参考资料 效果一览 文章概述 1.时序预测 | Transformer时间序列预测 Matlab代码 2.单变量时间序列预测&#xff1b; 3.多指标评价&#xff0c;评价指标包括&#xff1a;R2、MAE、MBE等&#xff0c;代码质量极高&#xff1b; 4.excel数据&…

QTableView获取可见的行数

场景 当我们需要实时刷新QTableView时&#xff0c;而此时tableView的数据量较大&#xff0c;如果全部刷新显然不合理&#xff0c;如果可以只对用户看的到的数据进行刷新那就最好了&#xff0c;经过一番摸索找到了几种方式&#xff0c;可供参考 代码 方法1 QVector<int>…

护眼台灯怎么选看哪些指标?五款性价比高的照明品牌综合对比

鉴于儿童近视率的不断攀升&#xff0c;为孩子打造一个优质的学习环境变得愈发关键。在这其中&#xff0c;护眼台灯无疑占据了举足轻重的地位。那么&#xff0c;护眼台灯怎么选看哪些指标&#xff1f;本文将详尽解析与护眼台灯密切相关的核心指标&#xff0c;帮助大家在选购时能…

数据结构中的顺序表的删除和查找

对于顺序表&#xff0c;它包括&#xff1a;初始化&#xff0c;取值&#xff0c;查找&#xff0c;插入&#xff0c;以及删除。接下来就讲一讲删除和查找。 删除&#xff1a;它包括头删和尾删&#xff0c;为什么顺序表中要用到删除呢&#xff1f;按我的理解就是&#xff1a;为插入…

Linux服务器硬件及RAID配置

一、服务器硬件 塔式服务器&#xff1a;最初的服务器形态之一&#xff0c;类似于传统的台式电脑&#xff0c;但具有更强的处理能力和稳定性&#xff0c;适合小型企业或部门使用。 机架式服务器&#xff1a;设计为可安装在标准化机架内的模块化单元&#xff0c;可以有效地节省空…

上位机图像处理和嵌入式模块部署(树莓派4b固件功能设计)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面我们说过&#xff0c;上位机的功能都是基于插件进行开发的。但是上位机的成本比较贵&#xff0c;一般的企业不一定愿意接接受。这个时候另外一…

Notion 开源替代品 AFFINE 部署和使用教程

AFFiNE 是一款完全开源的 Notion Miro 替代品&#xff0c;与 Notion 相比&#xff0c;AFFiNE 更注重隐私安全&#xff0c;优先将笔记内容保存到本地。 GitHub 地址&#xff1a;https://github.com/toeverything/AFFiNE AFFiNE 使用 Rust 和 Typescript 构建&#xff0c;只需…

重生奇迹mu怎么卡智力的方法

1、准备3个号A打手,B智力MM,C随意。 2、使用C匹配组队,但是不能选择自动进入队伍。 3、用A申请C的队伍,但是C不做通过处理。 4、用A组B,用快捷键D的方式。 5、所谓的卡智力就是智力MM可以给打手加属性加血&#xff0c;但是并不在一个队伍里享受经验&#xff0c;适用于MM不是…

Servlet第一篇【介绍Servlet、HTTP协议、WEB目录结构、编写入门Servlet程序、Servlet生命周期】

什么是Serlvet&#xff1f; Servlet其实就是一个遵循Servlet开发的java类。Serlvet是由服务器调用的&#xff0c;运行在服务器端。 为什么要用到Serlvet&#xff1f; 我们编写java程序想要在网上实现 聊天、发帖、这样一些的交互功能&#xff0c;普通的java技术是非常难完成…

【深度学习】最强算法之:Transformer

Transformer 1、引言2、Transformer2.1 引言2.2 核心概念2.3 应用2.4 算法公式2.5 代码示例 3、总结 1、引言 小屌丝&#xff1a;鱼哥&#xff0c;昨天的感受咋样 小鱼&#xff1a;啥感受啊&#xff1f; 小屌丝&#xff1a;你确定不知道&#xff1f; 小鱼&#xff1a;我… 小屌…

软考 - 系统架构设计师 - 设计模式

概念 每一个设计模式描述了一个在我们周围不断重复发生的问题&#xff0c;以及该问题解决方案的核心&#xff0c;这样&#xff0c;就可以在遇到相同的问题时使用该解决方案进行解决&#xff0c;不必进行重复的工作&#xff0c;设计模式的核心在于提供了问题的解决方案&#xff…

代码学习记录25---单调栈

随想录日记part45 t i m e &#xff1a; time&#xff1a; time&#xff1a; 2024.04.17 主要内容&#xff1a;今天开始要学习单调栈的相关知识了&#xff0c;今天的内容主要涉及&#xff1a;每日温度 &#xff1b;下一个更大元素 I 739. 每日温度 496.下一个更大元素 I Topic…

数仓建模—逻辑数据模型

数仓建模—逻辑数据模型 逻辑数据模型 (LDM Logical Data Model) 是一种详细描述数据元素的数据模型,用于开发对数据实体、属性、键和关系的直观理解。 这种模型独特地独立于特定的数据库,以便为数据管理系统中语义层的组件建立基础结构。将 LDM 视为一个蓝图:它代表在整个…

软件无线电安全之GNU Radio基础 -上

GNU Radio介绍 GNU Radio是一款开源的软件工具集&#xff0c;专注于软件定义无线电&#xff08;SDR&#xff09;系统的设计和实现。该工具集支持多种SDR硬件平台&#xff0c;包括USRP、HackRF One和RTL-SDR等。用户可以通过GNU Radio Companion构建流程图&#xff0c;使用不同…