Effective Java 学习笔记--42-44 函数接口及其应用(Lambda与方法引用)

news2024/9/21 19:29:24

目录

函数接口

标准函数接口

自定义函数接口

函数接口的应用

Lambda表达式

Lambda表达式相比于匿名类的优点

方法引用


函数式接口是只包含了一个抽象方法的接口,这种接口的设计目的是为了支持Lambda表达式为代表的函数输入,在Java中有43个标准的默认函数接口。本文会首先介绍标准的函数接口,然后介绍Lambda表达式和方法引用的使用,最后会对比它与匿名类以及方法引用的优劣。

函数接口

标准函数接口

Java.util.Function中共有43个标准的函数接口,但是最核心的基础接口只有6个,其余接口都是基于这些基础接口扩展出来的。下面重点介绍这6个基础接口:

接口函数签名说明范例方法
Function<T,R>R apply(T)函数输入T类型变量,转换为R类型输出Arrays::asList
UnaryOperator<T>T apply(T)函数输入T类型变量,输出也是同类型变量String::toLowerCase
BinaryOperator<T>T apply(T t1, T t2)函数输入两个T类型变量,输出同类型变量BigInteger:add
Predicate<T>boolean test(T)函数输入T类型,输出布林值Collection::isEmpty
Supplier<T>T get()函数无输入,输出T类型Instant:now
Consumer<T>void accept(T)函数输入T类型,无输入类型System.out::println

这6个基础接口各自有三种变体,分别可以作用于基本类型Int、long和double。他们的命名方式是在接口名称前面加上基本类型而得。比如IntPredicate的test方法要求输入类型为int。

另外,Function接口还有9种变体,用于结果类型为基本类型的情况。如果是基本类型转换为基本类型的情况命名格式为ScrToResult(LongToIntFunction),如果源类型为基础类型,结果类型为对象,命名格式为SrcToObj(DoubleToObjFunction)。

Function、Predicate和Consumer也有自己的二元参数版本(BiFunction<T, U, R>、BiPredicate(T, U)、BiConsumer(T, U)),然后Bifunction还有返回三个相关基本类型的变体(ToIntBiFunction、ToLongBiFunction、ToDoubleBiFunction),Consumer接口也有带两个参数的变体(一个对象引用、一个基本类型),ObjDoubleConsumer<T>、ObjIntConsumer<T>, ObjDoubleConsumer<T>。

最后还有一个Supplier接口的一种变体,BooleanSupplier接口。

自定义函数接口

除了以上标准的函数接口,程序员也可以通过@FunctionalInterface注释自行定义,如:

@FunctionalInterface
public interface CurrentTimePrinter {
    void printCurrentTime();
}

可以看到,这个函数式接口的方法没有输入和输出,不属于标准函数接口的任何一种场景。文中作者强调了尽量通过标准函数接口来实现相关的方法,除非是以下几种特殊的情况才可以考虑自定义函数式接口:

  • 确实没有符合要求的接口:这里有两种情况,一是输入和输出与标准接口不一致(如上面的例子),还有一种是需要抛出受检异常,这个功能并没有在标准接口方法中引入。
  • 接口的名称能够起到功能提示的作用:拿Comparator<T>接口为例,它与ToIntFunction<T,T>接口在结构上是一致的,但是Java中还是单独增加了这个接口,他的名称能起到很好的提示作用。
  • 需要有缺省的方法:Comparator<T>接口实现了大量的缺省方法,可以对比较器进行转换与合并。
  • 有关联的严格契约:还是拿Comparator<T>接口为例,它对于如何构成一个有效的实例有严格的限制(比如需要实现compare方法),这是标准接口所没有的。

函数接口的应用

Lambda表达式

与其他语言一样,Java允许通过Lambda表达式创建函数接口实例,它有些类似于匿名类,但是更加的简洁:

import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

public class Sample {
    public static void main(String[] args) {

        //Predicate接口实现
        Predicate<String> whetherisEmpty = (str)->str.isEmpty();
        System.out.println(whetherisEmpty.test(""));

        //Predicate接口实现
        Predicate<Integer>  isEven = (num)->num%2==0;
        System.out.println(isEven.test(4));

        //Consumer接口,用于打印给定的字符串到控制台。
        Consumer<String> printer = (str)-> System.out.println(str);
        printer.accept("Hello world");

        //定义一个Supplier接口,每次调用时返回一个新的随机字符串。
        Supplier<String> randomwordSupplier = ()->{
            String[] words ={"apple", "banana","orange","pear","grape"};
            return words[(int)Math.random()*words.length];
        };

        //Function应用
        Function<Person, String> personToString = (person)->{
            return person.getName();
        };


    }

    class Person{
        private String name;
        private int age;

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {}
    }
}

以上的案例都是独立创建函数式接口,然后调用接口的方法。当然也可以直接在以函数接口为参数的方法中直接引入Lambda表达式:


Collections.sort(words, (s1, s2)->compare(s1.length(), s2.length()));

这里编译器可以自动识别出Lambda的类型(Comparator<String>),s1和s2的类型(String),当然你也可以去注明这些类型,但是没有必要(除非Java的推断机制失效)。

Lambda表达式相比于匿名类的优点

匿名内部类是在Lambda表达式出现以前用来实现函数式接口嵌入的主要方法:

Collections.sort(words, new Comparator<String>(){
    @Override
    public int compare(String o1, String o2) {
        return o1.length()-o2.length();
    }
});

//注意接口可以通过匿名内部类的形式进行实例化,这在Java中是很常见的应用

相比于Lambda表达式,匿名类的实现有大量的样板代码,实现较为繁琐,但是如果实现的是非函数式接口(有多个方法),Lambda表达式就不起作用了。

方法引用

方法引用是比Lambda表达式更加简化的方法,相比于Lambda方法它进一步实现了参数的推断,因此使用的场景也更加有限(你要让程序可以推断出来)。比如书里的map.merge方法:

 

map.merge(key, 1, Integer::sum)

一般方法引用引用的是静态方法,但也有四种非静态方法的引用:

方法引用类型范例Lambda表达式说明
有限制非静态Instance.now()::isAfter

Instant then = Instance.now

t->then.isAfter(t)

有限制引用中,接收对象是在方法引用中临时指定的
无限制非静态String::toLowerCase(str)->str.toLowerCase()无限制引用中,需要通过在该方法的声明函数前面额外添加一个参数来指定:names.stream().map(String::toLowerCase),这里names就是实例
类构造器Tree<K, V>::new()-> new Tree<K, V>普通的类构造器
数组构造器int[]::new(len)-> new int[len]普通的数组构造器

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

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

相关文章

基于SpringBoot的旅游网站系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 基于JavaSpringBootVueMySQL的旅游网站系统【附源码文档】、…

远程连接Hiveserver2服务

目录 1.修改 core-site.xml 和 hive-site.xml 的配置文件 2.启动HiveServer2服务 3.启动Beeline工具连接Hiveserver2服务 4.利用IDEA工具连接Hiveserver2服务 完成Hive本地模式安装后&#xff0c;可以启动hiveserver2服务进行远程连接和操作Hive。 1.修改 core-site.xml …

ctf Mark loves cat (超详细记录)

分析&#xff1a;首先根据问题名称看不出明显的考点方向&#xff0c;先看了一下源代码&#xff0c;没有flag相关内容 我后面就去尝试sql注入方向&#xff0c;但是试了几个参数发现得到的回显都是一致的&#xff0c;全是主页&#xff0c;显然是做了错误重定向&#xff0c;那我就…

基于SpringBoot+Vue+MySQL的垃圾分类回收管理系统

系统展示 用户界面 管理员界面 系统背景 二十一世纪互联网的出现&#xff0c;改变了几千年以来人们的生活&#xff0c;不仅仅是生活物资的丰富&#xff0c;还有精神层次的丰富。在互联网诞生之前&#xff0c;地域位置往往是人们思想上不可跨域的鸿沟&#xff0c;信息的传播速度…

PhpStudy下载安装使用学习

一、官网下载 官网地址&#xff1a;Windows版phpstudy下载 - 小皮面板(phpstudy)https://old.xp.cn/download.html 【首页】选择Windows版&#xff0c;进行下载 下载完成是一个压缩包的形式&#xff0c;解压得到一个.exe的执行文件&#xff0c;点击执行安装程序&#xff08;注…

016.Python爬虫系列_关于登录和验证码

我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈 入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈 虚 拟 环 境 搭 建 :👉👉 Python项目虚拟环境(超详细讲解) 👈👈 PyQt5 系 列 教 程:👉👉 Python GUI(PyQt5)文章合集 👈👈 Oracle数…

BMP280气压传感器详解(STM32)

目录 一、介绍 二、传感器原理 1.原理图 2.引脚描述 3.传感器数据获取流程 三、程序设计 main.c文件 bmp280.h文件 bmp280.c文件 四、实验效果 五、资料获取 项目分享 一、介绍 BMP280是一款基于博世公司APSM工艺的小封装低功耗数字复合传感器&#xff0c;它可以测…

circuitjs 继电器使用的注意事项及疑惑解答

本篇是关于继电器使用中的一些注意事项, 及疑惑解答. 我们会深入分析下继电器外在行为表现的内在原因, 并针对一些异常情况提出解决方案. 两个输出端点都显示为高电平 在你使用继电器的过程中, 你可能注意到一种令人困惑的现象, 两个输出端有一个明明没有连接到电源, 却也显示…

Docker方式部署ProxySQL和Keepalived组合实现MGR的高可用访问

ProxySQL 代理访问MGR&#xff0c;可以做到故障自动切换主节点&#xff0c;可以自定义访问规则实现读写分离 目录 网络架构一、环境准备二、软件安装1. MGR集群配置2. 创建必要用户2. ProxySQL部署测试3. Keepalived部署高可用4. 测试高可用 网络架构 一、环境准备 三台物理主…

Ubuntu22.04之禁止内核自动更新(二百六十八)

简介&#xff1a; CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a; 多媒体系统工程师系列【…

2516. 每种字符至少取 K 个 滑动窗口 正难则反

给你一个由字符 a、b、c 组成的字符串 s 和一个非负整数 k 。每分钟&#xff0c;你可以选择取走 s 最左侧 还是 最右侧 的那个字符。 你必须取走每种字符 至少 k 个&#xff0c;返回需要的 最少 分钟数&#xff1b;如果无法取到&#xff0c;则返回 -1 。 示例 1&#xff1a; …

专注LabVIEW 做好一件事

在一次LabVIEW的系统改造项目中&#xff0c;遇到一个设备&#xff0c;操作手册居然还是基于DOS系统的。不难看出&#xff0c;这套设备虽然年代久远&#xff0c;但背后的技术积淀极为深厚。事实证明&#xff0c;这套系统在业内享有很高的认可度&#xff0c;由国外团队开发&#…

翻译神器大盘点:哪些软件让语言障碍不再是问题

如果你渴望提升外文阅读能力&#xff0c;却面临外语基础薄弱的挑战&#xff0c;不必过于担心。幸运的是&#xff0c;当前科技为我们提供了诸多便捷的解决方案——翻译工具。比如百度在线翻译这些工具功能强大&#xff0c;极大地拓宽了我们在日常生活与学习中的语言应用边界。 …

PHP轻松创建高效收集问卷调查小程序系统源码

轻松创建&#xff0c;高效收集 —— 问卷调查小程序&#xff0c;你的调研神器&#xff01; 一、告别繁琐&#xff0c;一键开启调研之旅 还在为设计问卷、收集数据而头疼不已吗&#xff1f;现在&#xff0c;有了“问卷调查小程序”&#xff0c;一切都变得轻松简单&#xff01;无…

戏曲文化苑管理系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;操作日志管理&#xff0c;基础数据管理&#xff0c;公告管理&#xff0c;戏曲管理&#xff0c;用户管理&#xff0c;轮播图信息 微信端账号功能包括&#xff1a;系统首页&#…

向改变技术世界的“导师们”致敬

在教师节这个特殊的日子里&#xff0c;我们通常向那些在课堂上辛勤工作的教师表达敬意&#xff0c;但在技术领域&#xff0c;也有一些导师通过他们的思想、发明和贡献&#xff0c;深刻改变了我们的世界。今天&#xff0c;让我们向那些改变技术世界的导师们致敬&#xff0c;他们…

VUCA时代与传统企业数字化转型

VUCA时代是一个具有现代概念的词&#xff0c;它代表了当前社会和经济环境的一种普遍特征。VUCA是Volatility&#xff08;易变性&#xff09;、Uncertainty&#xff08;不确定性&#xff09;、Complexity&#xff08;复杂性&#xff09;和Ambiguity&#xff08;模糊性&#xff0…

C#笔记8 线程是什么?多线程怎么实现和操作?

这和前面的学习内容可能有点不太连贯&#xff0c;但是呢我们一般来说的学习就是遇到什么困难就去学习什么&#xff0c;这也是为什么看那些循序渐进的教程虽然学的很饱满&#xff0c;但是我们有时会学了前面忘记了后面&#xff0c;或者对某个板块理解不深&#xff0c;乃至于写代…

递归搜索与回溯专题篇二

目录 N皇后 有效的数独 解数独 单词搜索 黄金矿工 不同路径III N皇后 题目 思路 根据题意可知&#xff0c;要想得到n皇后的摆放方案&#xff0c;结果须满足每一行及每一列都只有一个皇后&#xff0c;且每个主对角线和副对角线上只能有一个皇后&#xff0c;我们的做法是&…

STM32单片机 定时器TIM输出比较 PWM波形

一. OC&#xff08;Output Compare&#xff09;输出比较 了解&#xff1a;IC&#xff08;Input Capture&#xff09;输入捕获、CC&#xff08;Capture/Compare&#xff09;输入捕获和输出比较单元功能&#xff1a;用来输出PWM波形&#xff0c;PWM波形又是用来驱动电机的必要条…