Java Function 的妙用:化繁为简的魔法师!

Java Function 的妙用:化繁为简的魔法师!

在 Java 开发中,Function 是一个非常重要的函数式接口,它的存在让代码从繁琐走向简洁,从普通迈向优雅。今天,我们就来聊聊 Function 的那些“妙用”,以及它如何帮助开发者写出更简洁、更强大的代码。


一、什么是 Function?

Function 是 Java 8 中引入的一个函数式接口,定义在 java.util.function 包中。它接受一个输入参数,并返回一个结果。

核心方法

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
}

换句话说:

  • 输入一个 T,输出一个 R
  • 它是数据“加工”的工具。

简单例子:

import java.util.function.Function;

public class FunctionDemo {
    public static void main(String[] args) {
        Function<String, Integer> stringLength = str -> str.length();
        System.out.println(stringLength.apply("Hello, Function!")); // 输出 15
    }
}

二、Function 的常见妙用

1. 转换数据类型

很多时候,我们需要把一种类型的数据转换成另一种类型,比如将 String 转换成 Integer

Function<String, Integer> parseInt = Integer::parseInt;
System.out.println(parseInt.apply("123")); // 输出 123
再进一步:批量处理

配合 stream(),我们可以对列表中的数据批量转换。

import java.util.List;
import java.util.stream.Collectors;

public class BulkProcessing {
    public static void main(String[] args) {
        List<String> numbers = List.of("1", "2", "3");
        List<Integer> result = numbers.stream()
                                      .map(Integer::parseInt)
                                      .collect(Collectors.toList());
        System.out.println(result); // 输出 [1, 2, 3]
    }
}

2. 组合函数

Function 提供了两个强大的方法:andThencompose,可以将多个函数组合起来,让代码逻辑更加清晰。

(1) andThen: 先执行当前函数,再执行参数中的函数
Function<Integer, Integer> multiplyBy2 = x -> x * 2;
Function<Integer, Integer> add3 = x -> x + 3;

Function<Integer, Integer> combined = multiplyBy2.andThen(add3);
System.out.println(combined.apply(5)); // (5 * 2) + 3 = 13
(2) compose: 先执行参数中的函数,再执行当前函数
Function<Integer, Integer> combined2 = multiplyBy2.compose(add3);
System.out.println(combined2.apply(5)); // (5 + 3) * 2 = 16
(3) 实际应用场景:处理复杂数据

假设一个用户的年龄需要经过两个步骤处理:

  • 步骤 1:从 String 转成 Integer
  • 步骤 2:乘以系数 2。
Function<String, Integer> parseAndDouble = Integer::parseInt
        .andThen(age -> age * 2);
System.out.println(parseAndDouble.apply("20")); // 输出 40

3. 提取公共逻辑,减少代码重复

在实际开发中,我们常常遇到相似的逻辑,比如对一组数据进行校验或格式化。通过 Function,这些重复逻辑可以被抽象出来。

需求:对一组用户名字进行格式化

传统写法:

List<String> names = List.of(" ALICE ", " bOB", "CHARLIE ");
List<String> formattedNames = new ArrayList<>();
for (String name : names) {
    formattedNames.add(name.trim().toUpperCase());
}
System.out.println(formattedNames); // [ALICE, BOB, CHARLIE]

使用 Function 的写法:

Function<String, String> formatName = name -> name.trim().toUpperCase();
List<String> formattedNames = names.stream()
                                   .map(formatName)
                                   .collect(Collectors.toList());
System.out.println(formattedNames); // [ALICE, BOB, CHARLIE]
优点
  • 逻辑更简洁。
  • 格式化逻辑可以复用。

4. 实现策略模式

通过 Function,我们可以轻松实现策略模式,让代码逻辑更加灵活。

需求:根据不同的用户类型,计算不同的折扣
import java.util.Map;
import java.util.function.Function;

public class StrategyPattern {
    public static void main(String[] args) {
        Map<String, Function<Double, Double>> discountStrategies = Map.of(
            "VIP", price -> price * 0.8,
            "Regular", price -> price * 0.9,
            "Guest", price -> price
        );

        double price = 100.0;
        System.out.println("VIP: " + discountStrategies.get("VIP").apply(price));       // 80.0
        System.out.println("Regular: " + discountStrategies.get("Regular").apply(price)); // 90.0
        System.out.println("Guest: " + discountStrategies.get("Guest").apply(price));     // 100.0
    }
}
优点
  • 新增策略时,只需添加一条 Map 配置。
  • 逻辑清晰,易于扩展。

5. 延迟计算与缓存

Function 还可以用来实现一些简单的延迟计算或缓存逻辑。例如:

需求:计算数据并缓存结果
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

public class CacheDemo {
    public static void main(String[] args) {
        Map<Integer, String> cache = new HashMap<>();
        Function<Integer, String> fetchData = id -> cache.computeIfAbsent(id, key -> {
            System.out.println("Fetching data for " + key);
            return "Data for ID: " + key;
        });

        System.out.println(fetchData.apply(1)); // 第一次计算
        System.out.println(fetchData.apply(1)); // 从缓存中获取
    }
}

输出:

Fetching data for 1
Data for ID: 1
Data for ID: 1
优点
  • 避免重复计算。
  • 配合 computeIfAbsent,逻辑更简洁。

三、总结

Function 是 Java 中一个非常灵活的工具,可以用来简化代码逻辑、提高代码复用性。以下是一些最佳实践:

使用场景回顾

  1. 数据转换:将一种类型的数据轻松转换为另一种类型。
  2. 函数组合:通过 andThencompose 构建复杂逻辑。
  3. 公共逻辑抽取:减少代码重复。
  4. 策略模式:让代码逻辑灵活易扩展。
  5. 延迟计算与缓存:高效管理数据处理。

开发者金句

用好 Function,代码简洁到飞起!

希望本文能为你带来灵感,帮助你在日常开发中灵活运用 Function,写出更优雅的代码!如果你有其他妙用,欢迎留言分享~ 😊

推荐阅读文章

  • 由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)
  • 如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系
  • HTTP、HTTPS、Cookie 和 Session 之间的关系
  • 什么是 Cookie?简单介绍与使用方法
  • 什么是 Session?如何应用?
  • 使用 Spring 框架构建 MVC 应用程序:初学者教程
  • 有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误
  • 如何理解应用 Java 多线程与并发编程?
  • 把握Java泛型的艺术:协变、逆变与不可变性一网打尽
  • Java Spring 中常用的 @PostConstruct 注解使用总结
  • 如何理解线程安全这个概念?
  • 理解 Java 桥接方法
  • Spring 整合嵌入式 Tomcat 容器
  • Tomcat 如何加载 SpringMVC 组件
  • “在什么情况下类需要实现 Serializable,什么情况下又不需要(一)?”
  • “避免序列化灾难:掌握实现 Serializable 的真相!(二)”
  • 如何自定义一个自己的 Spring Boot Starter 组件(从入门到实践)
  • 解密 Redis:如何通过 IO 多路复用征服高并发挑战!
  • 线程 vs 虚拟线程:深入理解及区别
  • 深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别
  • 10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!
  • “打破重复代码的魔咒:使用 Function 接口在 Java 8 中实现优雅重构!”
  • Java 中消除 If-else 技巧总结
  • 线程池的核心参数配置(仅供参考)
  • 【人工智能】聊聊Transformer,深度学习的一股清流(13)
  • Java 枚举的几个常用技巧,你可以试着用用

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【最新鸿蒙开发之性能优化——动态加载和延迟加载】

大家好&#xff0c;我是学徒小z&#xff0c;在经历了一段时间项目开发中&#xff0c;我也渐渐意识到了性能的重要性&#xff0c;今天就分享一篇优化应用运行性能的文章&#xff0c;话不多说&#xff0c;开干&#xff01; 引言 延时触发操作与延迟加载的简介 动态加载&#x…

云计算研究实训室建设方案

一、引言 随着云计算技术的迅速发展和广泛应用&#xff0c;职业院校面临着培养云计算领域专业人才的迫切需求。本方案旨在构建一个先进的云计算研究实训室&#xff0c;为学生提供一个集理论学习、实践操作、技术研发与创新于一体的综合性学习平台&#xff0c;以促进云计算技术…

信号保存和信号处理

目录 信号保存中重要的概念 内核中信号的保存 对sigset_t操作的函数 对block&#xff0c;pendding&#xff0c;handler三张表的操作 sigpromask ​编辑 sigpending 是否有sighandler函数呢&#xff1f; 案例 信号处理 操作系统是如何运行的&#xff1f; 硬件中断 …

用vscode编写verilog时,如何有信号定义提示、信号定义跳转(go to definition)、模块跳转(跨文件跳转)这些功能

&#xff08;一&#xff09;方法一&#xff1a;安装插件SystemVerilog - Language Support 安装一个vscode插件即可&#xff0c;插件叫SystemVerilog - Language Support。虽然说另一个插件“Verilog-HDL/SystemVerilog/Bluespec SystemVerilog”也有信号提示及定义跳转功能&am…

初识算法 · 模拟(1)

目录 前言&#xff1a; 替换所有的问号 题目解析 算法原理 算法编写 提莫攻击 题目解析 算法原理 算法编写 外观数列 题目解析 算法原理 算法编写 前言&#xff1a; ​本文的主题是模拟&#xff0c;通过三道题目讲解&#xff0c;一道是提莫攻击&#xff0c;一道是…

〔 MySQL 〕数据类型

目录 1.数据类型分类 2 数值类型 2.1 tinyint类型 2.2 bit类型 2.3 小数类型 2.3.1 float 2.3.2 decimal 3 字符串类型 3.1 char 3.2 varchar 3.3 char和varchar比较 4 日期和时间类型 5 enum和set mysql表中建立属性列&#xff1a; 列名称&#xff0c;类型在后 n…

数据结构王道P234第二题

#include<iostream> using namespace std; int visit[MAxsize]; int color[MaxSize];//1表示红&#xff0c;2表示白&#xff1b; bool dfs(Graph G, int i){visit[i]1;ArcNode *p;bool flag1;for(pG.vertices[i].firsrarc; p ; pp->next){int jp->adjvex;if(!visi…

算法——两两交换链表中的节点(leetcode24)

这是一道对于链表节点进行操作的题目非常考验对于链表操作的基本功&#xff1b; 解法: 本题的解法结合下图来进一步解释 创建一个虚拟节点指向头结点以便使代码逻辑看起来更为简便且操作节点容易,定义cur是为了方便找到cur之后的两个节点进行交换操作定义pre和aft是为了保存执…

【AI图像生成网站Golang】项目架构

AI图像生成网站 目录 一、项目介绍 二、雪花算法 三、JWT认证与令牌桶算法 四、项目架构 五、图床上传与图像生成API搭建 六、项目测试与调试(等待更新) 四、项目架构 本项目的后端基于Golang和Gin框架开发&#xff0c;主要包括的模块有&#xff1a; backend/ ├── …

翼鸥教育:从OceanBase V3.1.4 到 V4.2.1,8套核心集群升级实践

引言&#xff1a;自2021年起&#xff0c;翼鸥教育便开始应用OceanBase社区版&#xff0c;两年间&#xff0c;先后部署了总计12套生产集群&#xff0c;其中核心集群占比超过四分之三&#xff0c;所承载的数据量已突破30TB。自2022年10月&#xff0c;OceanBase 社区发布了4.2.x 版…

ESP32-S3模组上跑通esp32-camera(19)

接前一篇文章&#xff1a;ESP32-S3模组上跑通esp32-camera&#xff08;18&#xff09; 本文内容参考&#xff1a; esp32-camera入门&#xff08;基于ESP-IDF&#xff09;_esp32 camera-CSDN博客 OV5640手册解读-CSDN博客 ESP32_CAM CameraWebServer例程源码解析笔记&#xf…

vmWare虚拟环境centos7安装Hadoop 伪分布式实践

背景&#xff1a;近期在研发大数据中台&#xff0c;需要研究Hadoop hive 的各种特性&#xff0c;需要搭建一个Hadoop的虚拟环境&#xff0c;本来想着使用dock &#xff0c;但突然发现docker 公共仓库的镜像 被XX 了&#xff0c;无奈重新使用vm 搭建虚拟机。 大概经历了6个小时完…

ARM(安谋) China处理器

0 Preface/Foreword 0.1 参考博客 Cortex-M23/M33与STAR-MC1星辰处理器 ARM China&#xff0c;2018年4月established&#xff0c;独立运行。 1 处理器类型 1.1 周易AIPU 1.2 STAR-MC1&#xff08;星辰处理器&#xff09; STAT-MC1&#xff0c;主要为满足AIOT应用性能、功…

c++--------《set 和 map》

c--------《set 和 map》 1 set系列的使⽤1.1 set类的介绍1.2 set的构造和迭代器1.3 set重要接口 2 实现样例2.1: insert和迭代器遍历使⽤样例&#xff1a;2.2: find和erase使⽤样例&#xff1a; 练习3.map系列的使用3.1 map类的介绍3.1.1 pair类型介绍 3.2 map的数据修改3.3mu…

MySQL面试之底层架构与库表设计

华子目录 mysql的底层架构客户端连接服务端连接的本质&#xff0c;连接用完会立马丢弃吗解析器和优化器的作用sql执行前会发生什么客户端的连接池和服务端的连接池数据库的三范式 mysql的底层架构 客户端连接服务端 连接的本质&#xff0c;连接用完会立马丢弃吗 解析器和优化器…

vscode vite+vue3项目启动调试

1、经常我们在普通的项目中&#xff0c;如果算法并不复杂&#xff0c;那么基本上console.log就可以搞定&#xff0c;当然也可以直接alert&#xff0c;打包的时候如果不去掉&#xff0c;还会在发版中上接弹出&#xff0c;给你个惊喜。 2、碰到了有些算法过程比较复杂的情况下&a…

详解八大排序(一)------(插入排序,选择排序,冒泡排序,希尔排序)

文章目录 前言1.插入排序&#xff08;InsertSort&#xff09;1.1 核心思路1.2 实现代码 2.选择排序&#xff08;SelectSort&#xff09;2.1 核心思路2.2 实现代码 3.冒泡排序&#xff08;BubbleSort&#xff09;3.1 核心思路3.2 实现代码 4.希尔排序&#xff08;ShellSort&…

IPv6 NDP 记录

NDP&#xff08;Neighbor Discovery Protocol&#xff0c;邻居发现协议&#xff09; 是 IPv6 的一个关键协议&#xff0c;它组合了 IPv4 中的 ARP、ICMP 路由器发现和 ICMP 重定向等协议&#xff0c;并对它们作出了改进。该协议使用 ICMPv6 协议实现&#xff0c;作为 IPv6 的基…

【包教包会】CocosCreator3.x框架——带翻页特效的场景切换

一、效果演示 二、如何获取 1、https://gitee.com/szrpf/TurnPage 2、解压&#xff0c;导入cocos creator&#xff08;版本3.8.2&#xff09;&#xff0c;可以直接运行Demo演示 三、算法思路 1、单场景 页面预制体 通过loadScene来切换页面&#xff0c;无法实现页面特效。…

拉取docker镜像应急方法

发现许多docker hub镜像网址速度也慢得发指啦&#xff0c;如果想速度快点&#xff0c;可以考虑买个按量计费的公有云服务器&#xff0c;用他们的内网镜像&#xff0c;然后再导出&#xff0c;然后传到本地。 开通服务器 可以考虑个开通最低配的&#xff0c;这里我用的是腾讯的…