Java8实战-总结11

Java8实战-总结11

  • Lambda表达式
    • 方法引用
      • 管中窥豹
        • 如何构建方法引用
      • 构造函数引用

Lambda表达式

方法引用

方法引用让你可以重复使用现有的方法定义,并像Lambda一样传递它们。在一些情况下,比起使用Lambda表达式,它们似乎更易读,感觉也更自然。下面就是借助更新的Java 8 API,用方法引用写的一个排序的例子:
先前:
3

inventory.sort((Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));

之后(使用方法引用和java.util.Comparator.comparing):

inventory.sort (comparing(Apple::getWeight));

管中窥豹

为什么应该关心方法引用?方法引用可以被看作仅仅调用特定方法的Lambda的一种快捷写法。它的基本思想是,如果一个Lambda代表的只是“直接调用这个方法”,那最好还是用名称来调用它,而不是去描述如何调用它。事实上,方法引用就是让你根据已有的方法实现来创建Lambda表达式。但是,显式地指明方法的名称,代码的可读性会更好。它是如何工作的呢?当需要使用方法引用时,目标引用放在分隔符::前,方法的名称放在后面。例如,Apple::getWeight就是引用了Apple类中定义的方法getWeight请记住,不需要括号,因为没有实际调用这个方法。方法引用就是Lambda表达式(Apple a) -> a.getWeight()的快捷写法。下表给出了Java 8中方法引用的其他一些例子。
在这里插入图片描述

可以把方法引用看作针对仅仅涉及单一方法的Lambda的语法糖,因为你表达同样的事情时要写的代码更少了。

如何构建方法引用

方法引用主要有三类。

  • 指向静态方法的方法引用(例如IntegerparseInt方法,写作Integer::parseInt)。
  • 指向任意类型实例方法的方法引用(例如Stringlength方法,写作String::length)。
  • 指向现有对象的实例方法的方法引用(假设有一个局部变量expensiveTransaction用于存放Transaction类型的对象,它支持实例方法getValue,那么你就可以写expensiveTransaction::getValue)。

第二种和第三种方法引用可能乍看起来有点儿晕。类似于string::length的第二种方法引用的思想就是在引用一个对象的方法,而这个对象本身是Lambda的一个参数。例如,Lambda表达式(String s) -> .toUppeCase()可以写作String::toUpperCase。但第三种方法引用指的是,在Lambda中调用一个已经存在的外部对象中的方法。例如,Lambda表达式()->expensiveTransaction.getValue()可以写作expensiveTransaction::getValue。依照一些简单的方子,就可以将Lambda表达式重构为等价的方法引用,如下图所示:
在这里插入图片描述

请注意,还有针对构造函数、数组构造函数和父类调用(super-call)的一些特殊形式的方法引用。举一个方法引用的具体例子吧。比方说想要对一个字符串的List排序,忽略大小写。Listsort方法需要一个Comparator作为参数。在前面看到,Comparator描述了一个具有(T, T)->int签名的函数描述符。可以利用string类中的compareToIgnoreCase方法来定义一个Lambda表达式(注意compareToIgnoreCaseString类中预先定义的)。

List<String> str = Arrays.asList("a","b","A","B");
str.sort((s1, s2)-> s1.compareToIgnorecase(s2));

Lambda表达式的签名与Comparator的函数描述符兼容。利用前面所述的方法,这个例子可以用方法引用改写成下面的样子:

List<String> str = Arrays.asList("a","b","A","B");
str.sort(String::compareToIgnoreCase);

请注意,编译器会进行一种与Lambda表达式类似的类型检查过程,来确定对于给定的函数式接口,这个方法引用是否有效:方法引用的签名必须和上下文类型匹配。

测验:方法引用
下列Lambda表达式的等效方法引用是什么?
(1) Punction<String, Integer> stringToInteger = (String s) -> Integer.parseInt(s);(2)BiPredicatecList<String>, String> contains =(list, element) -> list.contains(element);答案如下。
(1)这个Lambda表达式将其参数传给了Integer的静态方法parseInt。这种方法接受一个需要解析的String,并返回一个Integer。因此,可以使用上图中的办法①(Lambda表达式调用静态方法)来重写Lambda表达式,如下所示:
Function<String, Integer>  stringToInteger = Integer::parseInt;
(2)这个Lambda使用其第一个参数,调用其contains方法。由于第一个参数是List类型的,可以使用上图中的办法②,如下所示:
BiPredicate<List<String>, String> contains = List::contains;
这是因为,目标类型描述的函数描述符是(List<String>, String) -> boolean,而List::contains可以被解包成这个函数描述符。

到目前为止,只展示了如何利用现有的方法实现和如何创建方法引用。但是也可以对类的构造函数做类似的事情。

构造函数引用

对于一个现有构造函数,可以利用它的名称和关键字new来创建它的一个引用:
ClassName::new。它的功能与指向静态方法的引用类似。例如,假设有一个构造函数没有参数。
它适合Supplier的签名() -> Apple。可以这样做:

//构造函数引用指向默认的Apple()构造函数
Supplier<Apple> c1 = Apple::new;
Apple a1 = c1.get();

这就等价于:

//调用Supplier的get方法将产生一个新的Apple
//利用默认构造函数创建Apple的Lambda表达式
Supplier<Apple> c1 = () -> new Apple();
Apple a1 = c1.get();

如果构造函数的签名是Apple(Integer weight),那么它就适合Function接口的签名,于是可以这样写:

//指向Apple(Integer weight)的构造函数引用
Function<Integer, Apple> c2 = Apple::new;
//调用该Function函数的apply方法,并给出要求的重量,将产生一个Apple
Apple a2 = c2.apply(110);

这就等价于:
用要求的重量创建一
个Apple的Lambda表

//用要求的重量创建一个Apple的Lambda表达式
FunctioncInteger,Apple> c2 =(weight)-> new Apple(weight);
//调用该Punction函数的apply方法,并给出要求的重量,将产生一个新的Apple对象
Apple a2 = c2.apply(110);

在下面的代码中,一个由Integer构成的List中的每个元素都通过前面定义的类似的map方法传递给了Apple的构造函数,得到了一个具有不同重量苹果的List:

//将构造函数引用传递给map方法List<Integer> weights = Arrays.asList(7,3,4,10);List<Apple> apples = map(weights, Apple::new);public static List<Apple> map(List<Integer> list, Function<Integer, Apple> f) {List<Apple> result = new ArrayList<>();for(Integer e: list) {result.add(f.apply(e));}return result;}

如果有一个具有两个参数的构造函数Apple(String color, Integer weight),那么它就适合BiFunction接口的签名,于是可以这样写:

//指向Apple(String color,Integer weight)的构造函数引用
BiPunction<String, Integer, Apple> c3 = Apple::new;
//调用该BiFunction函数的apply方法,并给出要求的颜色和重量,将产生一个新的Apple对象
Apple c3 = c3.apply("green", 110);

这就等价于:

//用要求的颜色和重量创建一个Apple的Lambda表达式
BiPunction<String, Integer, Apple> c3 = (color, weight) -> new Apple(color, weight);//调用该BiPunction函数的apply方法,并给出要求的颜色和重量,将产生一个新的Apple对象
Apple c3 = c3.apply("green", 110);

不将构造函数实例化却能够引用它,这个功能有一些有趣的应用。例如,可以使用Map来将构造函数映射到字符串值。创建一个giveMeFruit方法,给它一个String和一个Integer,它就可以创建出不同重量的各种水果:

static Map<String, Function<Integer, Fruit>> map = new HashMap<>();
static {map.put("apple", Apple::new);map.put("orange", Orange::new);// etc...
}//用map得到了一个Function<Integer, Fruit>
public static Fruit giveMeFruit(String fruit, Integer weight) {//用Integer类型的weight参数调用Function的apply()方法将提供所要求的Fruitreturn map.get(fruit.toLowercase()).apply(weight);
}
测验:构造函数引用
已经看到了如何将有零个、一个、两个参数的构造函数转变为构造函数引用。那要怎么样才能对具有三个参数的构造函数,比如Color(int,int,int),使用构造函数引用呢?答案:构造函数引用的语法是ClassName::new,那么在这个例子里面就是Color::new。但是需要与构造函数引用的签名匹配的函数式接口。
但是语言本身并没有提供这样的函数式接口,可以自己创建一个:
public interface TriFunction<T,U, V, R> {R apply(T t,U u,V v);
}
现在可以像下面这样使用构造函数引用了:
TriPunction<Integer, Integer, Integer, Color> colorFactory = Color::new;

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

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

相关文章

算法竞赛入门【码蹄集新手村600题】(MT1120-1140)C语言

算法竞赛入门【码蹄集新手村600题】(MT1120-1140&#xff09;C语言 目录MT1121 小码哥考完咯MT1122阶梯IF-ELSEMT1123 元音MT1124 罗马数字MT1125 几月份MT1126 十二生肖MT1127 小码哥的属相MT1128 骰子的反面MT1129 小码哥玩骰子MT1130 骰子里面的数学MT1131 字符判断MT1132 人…

SciencePub学术 | 算法类重点SCIEEI征稿中

SciencePub学术 (www.sciencepub.cn) 刊源推荐: 算法类重点SCIE&EI征稿中&#xff01;2区闭源好刊&#xff0c;对国人非常友好。信息如下&#xff0c;录满为止&#xff1a; 一、期刊概况&#xff1a; 算法类重点SCIE&EI 【期刊简介】IF&#xff1a;6.0-6.5&#xff0…

Acwing.876 快速幂求逆元

题目 给定n组ai ,pi&#xff0c;其中p;是质数,求α;模p;的乘法逆元&#xff0c;若逆元不存在则输出impossible。 输入格式 第一行包含整数n。 接下来n行&#xff0c;每行包含一个数组ai, pi&#xff0c;数据保证p;是质数。 输出格式 输出共n行&#xff0c;每组数据输出一…

钉钉对接打通金蝶云星空获取流程实例列表详情(宜搭)接口与其他应收单接口

钉钉对接打通金蝶云星空获取流程实例列表详情&#xff08;宜搭&#xff09;接口与其他应收单接口 对接系统钉钉 钉钉&#xff08;DingTalk&#xff09;是阿里巴巴集团专为中国企业打造的免费沟通和协同的多端平台&#xff0c;提供PC版&#xff0c;Web版和手机版&#xff0c;有考…

pytorch学习——卷积神经网络——以LeNet为例

目录 一.什么是卷积&#xff1f; 二.卷积神经网络的组成 三.卷积网络基本元素介绍 3.1卷积 3.2填充和步幅 3.2.1填充&#xff08;Padding&#xff09; 填充是指在输入数据周围添加额外的边界值&#xff08;通常是零&#xff09;&#xff0c;以扩展输入的尺寸。填充可以在卷…

Git工具安装

Git 工具安装 1. 下载Git安装包2. 安装Git工具3. 简单的使用配置用户名 1. 下载Git安装包 打开官网 https://git-scm.com/downloads点击下载 2. 安装Git工具 右击以管理员身份运行 ![在这里插入图片描述](https://img-blog.csdnimg.cn/9a99a73d54824800bc87db64f71f7602.png…

避免安装这5种软件,手机广告频繁弹窗且性能下降

在我们使用手机的日常生活中&#xff0c;选择合适的应用软件对于保持良好的使用体验至关重要。然而&#xff0c;有些软件可能会给我们带来不必要的麻烦和困扰。特别是那些频繁弹窗广告、导致手机性能下降的应用程序&#xff0c;我们应该尽量避免安装它们。 首先第一种&#xf…

Python-面向对象:面向对象、成员方法 、类和对象、构造方法、魔术方法、封装、继承、类型注解、多态(抽象类(接口))

版本说明 当前版本号[20230806]。 版本修改说明20230806初版 目录 文章目录 版本说明目录知识总览图面向对象初识对象生活中数据的组织程序中数据的组织使用对象组织数据 成员方法类的定义和使用成员变量和成员方法成员方法的定义语法注意事项 类和对象现实世界的事物和类使…

快速开发平台 WebBuilder 9 发布

WebBuilder 是一款强大&#xff0c;全面和高效的应用开发和运行平台。基于浏览器的集成开发环境&#xff0c;智能化的设计&#xff0c;能轻松完成常规桌面应用和面向手机等的移动应用开发。高效、稳定和可扩展的特点&#xff0c;适合复杂企业级应用的运行。跨平台、数据库和浏览…

【Spring Cloud 四】Ribbon负载均衡

Ribbon负载均衡 系列文章目录背景一、什么是Ribbon二、为什么要有Ribbon三、使用Ribbon进行负载均衡服务提供者A代码pom文件yml配置文件启动类controller 服务提供者Bpom文件yml配置文件启动类controller 服务消费者pom文件yml文件启动类controller 运行测试 四、Ribbon的负载均…

0140 数据链路层2

目录 3.数据链路层 3.6局域网 3.7广域网 3.8数据链路层设备 部分习题 3.数据链路层 3.6局域网 3.7广域网 3.8数据链路层设备 部分习题 1.如果使用5类UTP来设计一个覆盖范围为200m的10BASE-T以太网&#xff0c;需要采用的设备是&#xff08;&#xff09; A.放大器 …

Selenium入门详细教程+实例演示

目录 1.Selenium概述 1.1什么是Selenium 1.2Selenium的优势 1.3Selenium WebDriver原理 2.Selenium环境搭建 3.Selenium 简单示例 4.八大元素定位 4.1定位方式 4.2定位方式的用法 5.Selenium API 5.1WebDriver 常用 API 5.2WebElement 常用 API 5.3代码示例 6.元素等待机…

阿里云瑶池 PolarDB 开源官网焕新升级上线

导读近日&#xff0c;阿里云开源云原生数据库 PolarDB 官方网站全新升级上线。作为 PolarDB 开源项目与开发者、生态伙伴、用户沟通的平台&#xff0c;将以开放、共享、促进交流为宗旨&#xff0c;打造开放多元的环境&#xff0c;以实现共享共赢的目标。 立即体验全新官网&…

【华秋推荐】物联网入门学习模块 ESP8266

随着全球信息技术的不断进步和普及&#xff0c;物联网成为当今备受关注的技术热点之一。通过物理和数字设备之间的连接来实现自动化和互联互通的网络。无线传感器、云计算和大数据分析等技术&#xff0c;物联网使设备能够相互交流和共享信息&#xff0c;实现智能化的自动化操作…

.Net6 Core Web API 配置 log4net + MySQL

目录 一、导入NuGet 包 二、添加配置文件 log4net.config 三、创建MySQL表格 四、Program全局配置 五、帮助类编写 六、效果展示 小编没有使用依赖注入的方式。 一、导入NuGet 包 ---- log4net 基础包 ---- Microsoft.Extensions.Logging.Log4Net…

K8s集群安全机制

1.访问K8s集群的时候&#xff0c;需要经过三个步骤完成具体操作 &#xff08;1&#xff09;认证&#xff08;2&#xff09;鉴权&#xff08;授权&#xff09;&#xff08;3&#xff09;准入控制 进行访问的时候&#xff0c;过程中都要经过apiserver&#xff0c;apiserver做统…

Docker与DevOps的无敌组合,引爆你的创新潜能

&#x1f3c6;荣誉认证&#xff1a;51CTO博客专家博主、TOP红人、明日之星&#xff1b;阿里云开发者社区专家博主、技术博主、星级博主。 &#x1f4bb;微信公众号&#xff1a;iOS开发上架 &#x1f4cc;本文由iOS开发上架原创&#xff01; &#x1f389;欢迎关注&#x1f50e;…

【网络编程·传输层】UDP和TCP的报头

目录 一、端口号划分 二、部分指令 1、pidof&#xff08;用于查看进程id&#xff09; 2、netstat&#xff08;查看网络状态&#xff09; 三、UDP协议 1、UDP协议格式 2、UDP协议如何进行封装、解包、分用 2.1封装、解包 2.2分用 3、UDP协议的特点 3.1UDP协议的特点 …

C# 控制台彩色深度打印 工具类

文章目录 前言Nuget 环境安装代码使用打印结果 总结 前言 有时候我们想要靠打印获得程序信息&#xff0c;因为Dubeg模式需要一点一点断点进入进出&#xff0c;但是我们觉得断点运行实在是太慢了&#xff0c;还是直接打印后找结果会好一点。 Nuget 环境安装 想自己写的话可以看…

试卷去手写内容在线擦除,使用这个方法轻松达成

在数字时代&#xff0c;越来越多的人开始使用电子设备来完成日常任务。即使在考试时&#xff0c;许多学生也选择使用电子设备来写答案&#xff0c;而不是在试卷上手写。然而&#xff0c;有时候我们需要手写答案&#xff0c;但当我们想要更改或者擦除时&#xff0c;这将是一个麻…