盘点java8 stream中隐藏的函数式接口

news2024/9/18 13:04:12

shigen坚持更新文章的博客写手,记录成长,分享认知,留住感动。个人IP:shigen

提到函数式接口,最常见的就是lambda表达式,IDEA也有智能的提示:

idea智能提示

最后改成这样的就是最简洁的、IDEA希望的风格:

List<String> nameList = users.stream().map(User::getName).collect(Collectors.toList());
log.info("nameList:{}", nameList);

直接一行搞定比较复杂的功能。今天要讲到的函数式接口就从这个展开。

1. 函数式接口

所谓的函数式接口指的是只定义一个抽象方法的接口。接口类常用这个注解@FunctionalInterface表明:

  • java.util.Comparator
public interface Comparator<T> {
    int compare(T o1, T o2);
}
  • java.lang.Runnable
public interface Runnable {
    void run();
}
  • java.util.concurrent.Callable
public interface Callable<V> {
    V call() throws Exception;
}

实现起来基本上是这样的:

(o1, o2) -> o1.getXxx() > o2.getXxx()
() -> void
() -> V类型的对象

其中,callable最常见在多线程上,这里展示下我对于分布式锁的封装:

callable案例:分布式锁封装

2. 常用的函数式接口

或许对于Function、Predicate等等你并不陌生,好熟悉、好像在哪里用过就是想不起来!我们还是用stream()流来讲解。前提是构建一个用户列表:

构建数据

相信截图里User类的属性一目了然。现在我们用stream流来操作。

2.1 Function出现
List<String> nameList = users.stream().map(user -> user.getName()).collect(Collectors.toList());
log.info("nameList:{}", nameList);

这里的逻辑很简单,获得所有的用户名字返回集合。不知道有没有好奇过map,他的参数是什么:

map的参数

额,就是一个Function!好的,我这样改造下:

    static Function<User, String> nameFunction = user -> user.getName();

    public static void main(String[] args) {

        List<String> nameList = users.stream().map(nameFunction).collect(Collectors.toList());
        log.info("nameList:{}", nameList);
    }

其实Function就是两个类型约束,一个数参数类型,一个是返回值类型,定义了一个固定的逻辑。这个还好,如果稍加对于name的处理,并且是通用的处理方式,就可以考虑用Function写成一个通用的方法。

2.2 Predicate出现

Function类似,Predicate顾名思义,就是断言。可以从stream.filter()中获得:

User user1 = users.stream().filter(user -> "李四".equals(user.getName())).findFirst().orElse(null);
log.info("user1:{}", user1);

filter-predicate

对应的改造:

    static Predicate<User> namePredicate = user -> "李四".equals(user.getName());

    public static void main(String[] args) {
        User user1 = users.stream().filter(namePredicate).findFirst().orElse(null);
        log.info("user1:{}", user1);
    }

Predicate的范型只有一个,就是一个对象,返回的就是断言的方法。

2.3 Cousumer的出现

直接给出代码案例:

        Consumer<User> userConsumer = user -> {
            String name = user.getName();
            log.info("name:{}", name);
        };

        userConsumer.accept(users.get(0));

适用场景:访问类型T的对象,对其执行某些操作。只有操作,没有返回值,也不需要关注返回值。另外附上我最近看到的一段模板代码:

    /**
     * 利用设计模式减少样板代码
     */
    public static void readLine(String filename, Consumer<String> consumer) {
        try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
            String line;
            while ((line = reader.readLine()) != null) {
                consumer.accept(line);
            }
        } catch (IOException e) {
            throw new RuntimeException("Error reading file", e);
        }
    }



    public static void main(String[] args) {
        String filePath = "/Users/shigen/Downloads/area.json";
        readLine(filePath, (lines) -> {
            System.out.println(lines);
        });
    }  
2.4 Supplier的出现

还是先上代码:

        Supplier<User> userSupplier = () -> new User("10005", "shigen", null);
        User user2 = userSupplier.get();
        log.info("user2:{}", user2);
        userConsumer.accept(user2);

这里正好和Consumer相反,这里是生产对象的,然后可以供它消费。

适用场景:定义类型T的对象的生产规则。这里列出一个案例:生成随机数的方法:

        Supplier<Integer> randomSupplier = () -> new Random().nextInt(100);
        log.info("randomSupplier:{}", randomSupplier.get());

突然感觉曾经写过的工具类可以用这种方式简化一下了。

2.5 Comparator的出现

其实我们用的最多的还是实现Comparator的接口,重写compare方法用来比较对象,多见于需要内存排序的场景:

Comparator接口

也可以在stream.sorted()的参数中看出来:

stream.sorted()

        Comparator<User> userComparator =
            (user4, user5) -> user5.getName().compareTo(user4.getName());

        List<String> sortedName = users.stream().sorted(userComparator).map(User::getId).collect(Collectors.toList());
        log.info("sortedName:{}", sortedName);

当然,其它的高级复合Lambda表达式用法,可以参考这篇文章:系统学习lambda表达式。个人认为在业务代码使用复合lambda表达式,会加重代码的理解难度,不推荐。了解常见的函数式接口,并会使用即可。

与shigen一起,每天不一样!

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

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

相关文章

机器学习:基于机器学习的中文评论情感分析

通过机器学习技术对中文评论进行情感分析。我们使用了jieba进行中文分词&#xff0c;移除了停用词&#xff0c;并利用词袋模型&#xff08;Bag of Words&#xff09;和多项式朴素贝叶斯分类器对评论进行了情感分类。实验结果表明&#xff0c;该模型在测试集上达到了较高的准确率…

如何构建高效的中药材进存销管理系统?——运用Java SpringBoot和Vue实现库存实时监控,简化销售流程,提升药材管理效率。

&#x1f34a;作者&#xff1a;计算机毕设匠心工作室 &#x1f34a;简介&#xff1a;毕业后就一直专业从事计算机软件程序开发&#xff0c;至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长&#xff1a;按照需求定制化开发项目…

前端宝典二十一:前端异步编程规范手写Promise、async、await

本文主要探讨前端异步编程的处理方式、处理场景&#xff0c;并且手写Promise的全家桶&#xff0c;介绍async、await方法使用 一、异步处理方式有&#xff1a; 1. 回调函数 function fetchDate(callback) {setTimeout(() > {const date new Date();callback(date);}, 100…

SpringSecurity Oauth2 - 密码模式完成身份认证获取令牌 [自定义UserDetailsService]

文章目录 1. 授权服务器2. 授权类型1. Password (密码模式)2. Refresh Token&#xff08;刷新令牌&#xff09;3. Client Credentials&#xff08;客户端凭证模式&#xff09; 3. AuthorizationServerConfigurerAdapter4. 自定义 TokenStore 管理令牌1. TokenStore 的作用2. Cu…

嵌入式Linux C应用编程指南-高级I/O(速记版)

第十三章 高级I/O 13.1 非阻塞I/O 阻塞其实就是进入了休眠状态&#xff0c;交出了 CPU 控制权。比如 wait()、pause()、sleep()等函数都会进入阻塞。 阻塞式 I/O 顾名思义就是对文件的 I/O 操作&#xff08;读写操作&#xff09;是阻塞式的&#xff0c;非阻塞式 I/O 同理就是对…

SpringSecurity Oauth2 - 访问令牌续期

文章目录 1. 访问令牌的续期2. CustomUserDetailsService3. 配置 AuthorizationServerEndpointsConfigurer4. 测试项目 1. 访问令牌的续期 在Spring Security OAuth2中&#xff0c;访问令牌的续期通常是通过使用**刷新令牌&#xff08;Refresh Token&#xff09;**来实现的。当…

走进酒厂,探寻白酒酿造的奥秘

在华夏大地深处&#xff0c;隐藏着一座座充满神秘色彩的酒厂&#xff0c;它们是白酒酿造的地方&#xff0c;也是中华酒文化的摇篮。今天&#xff0c;就让我们一起走进这些酒厂&#xff0c;探寻白酒酿造的奥秘&#xff0c;感受豪迈白酒&#xff08;HOMANLISM&#xff09;的不同魅…

当网络适配器的Wireless出现感叹号

1.出现如下情况 链接&#xff1a; &#xff1a;一招搞定Intel(R) Wireless-AC 9560显示感叹号&#xff0c;无法打开wifi模块&#xff01;_intel(r)wireless-ac9560感叹号-CSDN博客z 重点&#xff1a; 原因是因为电脑静电的问题。

昇腾AI处理器的计算核心 - AI Core即DaVinci Core

昇腾AI处理器的计算核心 - AI Core即DaVinci Core flyfish 从一段代码的解释开始 template <typename T> class GlobalTensor { public:void setGlobalBuffer(T* buffer, uint32_t buffersize) {// 在这里实现设置全局缓冲区的逻辑} };语法的说明&#xff0c;主要用于…

封装_私有类字段和方法

前言 在 JavaScript 中&#xff0c;封装、私有类字段和方法是面向对象编程的一种重要特性。它们允许你将数据&#xff08;属性&#xff09;和对数据的操作&#xff08;方法&#xff09;组合在一起&#xff0c;并控制访问权限&#xff0c;从而提高代码的安全性和可维护性。私有…

异步编程详解

1.什么是async std::async:是一个函数模板,用于启动一个异步任务。它接受一个可调用的对象(如函数、Lambda表达式、函数对象)作为参数,并在一个单独的线程上异步执行对象。std::async自动管理异步任务的生命周期,并返回一个std::future对象,该对象用于获取异步操作的结果。 2.什…

【Java】—— Java面向对象进阶:继承小练习-Java中实现圆柱体类及其体积计算

目录 1. 定义圆类&#xff08;Circle&#xff09; 2. 定义圆柱体类&#xff08;Cylinder&#xff09; 3. 测试圆柱体类 4. 总结 在Java中&#xff0c;我们可以通过面向对象的方式来模拟现实世界中的物体&#xff0c;比如圆柱体。本篇文章将通过一个简单的示例来展示如何定义…

全国大学生数学建模竞赛系统使用手册

注意&#xff01;国赛是学校统一报名&#xff0c;所以如果在操作上有任何不清楚的地方&#xff0c;一定要在赛前即使询问自己学校组织数模的老师&#xff01;并详细阅读本文和官网通知&#xff0c;以及&#xff1a;数模国赛提交MD5码和论文的坑&#xff01; 数模比赛的建模手、…

【Python报错已解决】“ModuleNotFoundError: No module named ‘timm‘”

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 引言&#xff1a;一、问题描述1.1 报错示例&#xff1a;当我们尝试导入timm库时&#xff0c;可能会看到以下错误信息。…

颠覆传统:基于全文索引驱动下的高效一对多表结构设计!

首发公众号&#xff1a;赵侠客 引言 在数据库表结构设计中&#xff0c;一对多&#xff08;1:N&#xff09;关系的处理是非常常见需求&#xff0c;如一个用户有多个分类或角色。传统关系型数据库表设计方式通常要包括三张表&#xff1a;用户表、分类表、以及用户与分类之间的关…

LC开源电路的学习(一)

TI的升压芯片&#xff0c;电压虽然能升高&#xff0c;但是带来的问题就是最大电流大幅降低&#xff1a; CC1和CC2芯片接快充芯片之后&#xff0c;直接接到单片机的下载口&#xff1a; 这个有点意思&#xff0c;用导线换电阻&#xff1a; 、 PD快充芯片CH224K需要连接typeC的D…

华为云征文|基于Flexus云服务器X实例的应用场景-部署脚手架开源项目若依

&#x1f534;大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 先看这里 写在前面**Flexus X实例**的云服务器简介环境准备若依项目拉取导入数据库启动本地项目&#xff08;后端&#xff09;启动本地项目&#xff08;前端&#xff09;打包后…

图片转为PDF怎么弄?看这里,三款软件助你一键转换!

嘿&#xff0c;朋友们&#xff01;现在信息这么多&#xff0c;图片在我们学习、工作、生活中帮了大忙。但有时候&#xff0c;我们想把图片整理好、分享给别人或者打印出来&#xff0c;PDF格式就特别合适。PDF文件不管在哪儿打开&#xff0c;内容都不会变样&#xff0c;还能加密…

Pandas 9-绘制柱状图

1. 准备数据 首先&#xff0c;需要准备一个DataFrame。 import pandas as pd # 创建一个DataFrame data { Name: [Alice, Bob, Charlie, David], Age: [24, 27, 22, 32], City: [New York, Los Angeles, Chicago, Houston], Score: [85, 92, 78, 88]} df pd.…

【生成模型系列(初级)】自编码器——深度学习的数据压缩与重构

【通俗理解】自编码器——深度学习的数据压缩与重构 第一节&#xff1a;自编码器的类比与核心概念 1.1 自编码器的类比 你可以把自编码器想象成一个“智能压缩机”&#xff0c;它能够把输入的数据&#xff08;比如图片&#xff09;压缩成一个更小的表示&#xff08;编码&#…