当前位置: 首页 > news >正文

Java 函数式编程

引言

Java 8 引入的 Lambda 表达式和函数式接口,让 Java 具备了函数式编程的能力。函数式编程不是要替代面向对象,而是提供了一种更简洁、更具表达力的编程范式,特别适合集合操作、事件处理和异步编程。


一、Lambda 表达式

1.1 语法

// 完整语法(Type1param1,Type2param2)->{expression;returnvalue;}// 简化规则// 1. 类型推断:参数类型可省略(a,b)->a+b// 2. 单参数:括号可省略name->System.out.println(name)// 3. 单表达式:花括号和 return 可省略(a,b)->a+b// 4. 多行语句:需要花括号和 return(a,b)->{intsum=a+b;returnsum;}

1.2 常见用法

// 替代匿名内部类// BeforeRunnabler1=newRunnable(){@Overridepublicvoidrun(){System.out.println("hello");}};// AfterRunnabler2=()->System.out.println("hello");// ComparatorComparator<String>c1=(a,b)->a.length()-b.length();// 自定义接口@FunctionalInterfaceinterfaceStringProcessor{Stringprocess(Stringinput);}StringProcessortoUpper=s->s.toUpperCase();

1.3 变量捕获

// Lambda 可以捕获 effectively final 的局部变量Stringprefix="Hello, ";// effectively finalFunction<String,String>greeter=name->prefix+name;greeter.apply("Alice");// "Hello, Alice"// Lambda 内部不能修改捕获的变量// prefix = "Hi, "; // 编译错误

二、函数式接口

2.1 @FunctionalInterface

// 函数式接口:只包含一个抽象方法的接口@FunctionalInterfacepublicinterfaceConverter<T,R>{Rconvert(Tinput);}// 默认方法和静态方法不影响@FunctionalInterfacepublicinterfaceSmartConverter<T,R>{Rconvert(Tinput);defaultRconvertOrDefault(Tinput,RdefaultValue){returninput==null?defaultValue:convert(input);}static<T>SmartConverter<T,T>identity(){returnt->t;}}

2.2 JDK 内置函数式接口

接口参数返回用途示例
Supplier<T>T提供值() -> new Config()
Consumer<T>Tvoid消费值s -> log.info(s)
BiConsumer<T,U>T,Uvoid消费两个值(k,v) -> map.put(k,v)
Function<T,R>TR转换s -> s.length()
BiFunction<T,U,R>T,UR双参数转换(a,b) -> a + b
UnaryOperator<T>TT一元操作s -> s.trim()
BinaryOperator<T>T,TT二元操作(a,b) -> a + b
Predicate<T>Tboolean判断s -> s.isEmpty()
BiPredicate<T,U>T,Uboolean双参数判断(a,b) -> a.equals(b)

基本类型特化(避免装箱拆箱):

IntSuppliersupplier=()->42;// int -> intIntFunction<String>func=i->"N"+i;// int -> StringIntPredicatepred=i->i>0;// int -> booleanIntConsumerconsumer=i->log(i);// int -> voidIntUnaryOperatorop=i->i*2;// int -> intIntBinaryOperatorbinOp=(a,b)->a+b;// int,int -> int

三、方法引用

3.1 四种形式

形式语法等价 Lambda
静态方法引用ClassName::staticMethoda -> ClassName.staticMethod(a)
实例方法引用instance::methoda -> instance.method(a)
类型方法引用ClassName::method(obj, a) -> obj.method(a)
构造器引用ClassName::new() -> new ClassName()

3.2 示例

// 1. 静态方法引用Function<String,Integer>parser=Integer::parseInt;// 2. 实例方法引用Stringprefix="Hello, ";Function<String,String>greeter=prefix::concat;// 3. 类型方法引用(最常用)Function<String,Integer>lengthFn=String::length;BiPredicate<String,String>equalsFn=String::equals;// 4. 构造器引用Supplier<List<String>>listFactory=ArrayList::new;Function<Integer,int[]>arrayFactory=int[]::new;

3.3 方法引用 vs Lambda

// 优先使用方法引用,更简洁list.forEach(System.out::println);// 方法引用list.forEach(s->System.out.println(s));// Lambda,稍冗长// 方法引用无法表达时使用 Lambdalist.stream().map(s->s+"!");// Lambda

四、函数组合

4.1 Function 组合

Function<String,String>trim=String::trim;Function<String,String>toUpper=String::toUpperCase;Function<String,String>addPrefix=s->"Hello, "+s;// andThen:先执行当前,再执行参数Function<String,String>pipeline=trim.andThen(toUpper).andThen(addPrefix);Stringresult=pipeline.apply(" alice ");// "Hello, ALICE"// compose:先执行参数,再执行当前Function<String,String>pipeline2=addPrefix.compose(toUpper).compose(trim);Stringresult2=pipeline2.apply(" alice ");// "Hello, ALICE"

4.2 Predicate 组合

Predicate<String>nonEmpty=s->!s.isEmpty();Predicate<String>shortStr=s->s.length()<10;Predicate<String>startsWithA=s->s.startsWith("A");// and / or / negatePredicate<String>combined=nonEmpty.and(shortStr).and(startsWithA.negate());combined.test("Hello");// truecombined.test("ABCDEF");// false

4.3 Consumer 组合

Consumer<String>log=s->System.out.println("LOG: "+s);Consumer<String>audit=s->System.out.println("AUDIT: "+s);Consumer<String>logAndAudit=log.andThen(audit);logAndAudit.accept("user login");// LOG: user login// AUDIT: user login

五、高阶函数实战

5.1 策略模式

// 传统策略模式需要多个类// 函数式策略模式:用 Map + Lambda 替代Map<String,Function<Double,Double>>strategies=Map.of("regular",p->p*0.95,"vip",p->p*0.8,"svip",p->p*0.7);doublediscounted=strategies.getOrDefault(userLevel,p->p).apply(originalPrice);

5.2 装饰器模式

// 函数式装饰器Function<String,String>base=s->s;Function<Function<String,String>,Function<String,String>>trimDecorator=fn->s->fn.apply(s.trim());Function<Function<String,String>,Function<String,String>>upperDecorator=fn->s->fn.apply(s.toUpperCase());Function<Function<String,String>,Function<String,String>>prefixDecorator=fn->s->fn.apply(">> "+s);Function<String,String>decorated=trimDecorator.andThen(upperDecorator).andThen(prefixDecorator).apply(base);decorated.apply(" hello ");// ">> HELLO"

5.3 惰性求值

publicclassLazy<T>{privateSupplier<T>supplier;privateTvalue;privatebooleancomputed=false;publicLazy(Supplier<T>supplier){this.supplier=supplier;}publicTget(){if(!computed){value=supplier.get();computed=true;supplier=null;}returnvalue;}public<R>Lazy<R>map(Function<T,R>fn){returnnewLazy<>(()->fn.apply(this.get()));}public<R>Lazy<R>flatMap(Function<T,Lazy<R>>fn){returnnewLazy<>(()->fn.apply(this.get()).get());}}// 使用Lazy<String>lazy=newLazy<>(()->{System.out.println("Computing...");return"hello";});// 此时未计算Stringresult=lazy.get();// "Computing..." -> "hello"Stringagain=lazy.get();// 直接返回缓存值,不再计算

5.4 回调模式

public<T>voidexecuteAsync(Supplier<T>task,Consumer<T>onSuccess,Consumer<Exception>onError){newThread(()->{try{Tresult=task.get();onSuccess.accept(result);}catch(Exceptione){onError.accept(e);}}).start();}// 使用executeAsync(()->fetchData(),result->System.out.println("Success: "+result),error->System.err.println("Error: "+error.getMessage()));

六、常见陷阱

6.1 Lambda 中的 this

publicclassDemo{privateStringname="Outer";publicvoidtest(){// Lambda 中的 this 指向外部类实例Runnabler=()->System.out.println(this.name);// "Outer"// 匿名内部类中的 this 指向匿名类实例Runnabler2=newRunnable(){privateStringname="Inner";publicvoidrun(){System.out.println(this.name);// "Inner"}};}}

6.2 Lambda 与受检异常

// Lambda 中受检异常必须处理list.forEach(s->{try{Files.readString(Path.of(s));}catch(IOExceptione){thrownewUncheckedIOException(e);}});// 封装工具方法privatestatic<T>Supplier<T>unchecked(Callable<T>callable){return()->{try{returncallable.call();}catch(Exceptione){thrownewRuntimeException(e);}};}

6.3 Lambda 与重载歧义

// 编译错误:Lambda 类型推断歧义execute(()->{});// 是 Runnable 还是 Callable<Void>?// 显式指定类型execute((Runnable)()->{});execute((Callable<Void>)()->null);

总结

要点建议
Lambda优先替代匿名内部类
方法引用比 Lambda 更简洁时使用
函数式接口优先使用 JDK 内置接口
函数组合andThen/compose 构建处理管道
变量捕获effectively final,不要 hack
受检异常Lambda 中必须 try-catch 或包装
http://www.jsqmd.com/news/1058486/

相关文章:

  • 金融合规策略数据库设计:结构化存储与高性能查询优化实践
  • LLM驱动的文本相关性评估:从RAG到可持续性分析的工程实践
  • Linux命令-pvchange(修改物理卷属性)
  • 事件相机在视觉说话人识别中的应用:NeuroLip框架解析
  • 基于YOLOv8与RexNet-150的两阶段深度学习考试作弊检测框架实战
  • QGas工具:解决气体能源网络建模数据荒的拓扑感知数据生成方案
  • 极端天气下电力系统鲁棒调度优化实践
  • RAGognizer:基于幻觉感知微调提升大模型在RAG中的事实可靠性
  • 2026荆州漏水检测维修本地口碑防水商家榜单:厨卫/阳台/屋面/地下室渗漏水维修,持证施工+明码实价,防水补漏公司TOP5推荐 - 即刻修防水
  • AI动态简报之商业洞察篇(2026.06.21)
  • GoB插件:打破Blender与ZBrush之间的创作壁垒
  • Xournal++:如何用这款开源手写笔记软件彻底改变你的数字笔记体验?
  • 轻量级AI音乐生成模型TinyMU:2.29亿参数媲美大模型的架构与实战
  • SVGedit完全指南:5步掌握浏览器端矢量图形编辑
  • 基于RPA思想的Cassandra数据库自动化测试框架构建与实践
  • 高穹全域透视·智网自主抗毁|空基立体感知·全域精准管控
  • UniEditBench:基于知识蒸馏的统一多模态编辑评测基准
  • 基于SIVR的大语言模型幻觉检测:原理、实现与实战优化
  • 2023年图灵“贝利文件”近50万美元拍卖,揭秘其绝密“黛利拉”语音加密项目
  • LLM智能体架构设计:经验压缩谱实现记忆、技能与规则统一管理
  • 衍射光学神经网络物理鲁棒性分析:从数字优化到制造落地的系统方法
  • 光伏MPPT中PO算法收敛性增强:应对不确定性扰动的工程实践
  • 2026年当前安徽牯牛降网红漂流热门景区选择指南与品牌深度解析 - 品牌鉴赏官2026
  • DroidCam OBS插件终极指南:将手机摄像头变身高清直播摄像头
  • 第二代无服务器平台架构演进:从FaaS到一体化应用体验的实战解析
  • 大模型知识遗忘实战:基于反事实推理与偏好优化的可控遗忘技术
  • AI写作助手如何通过目标设定与元认知支持提升学术写作质量
  • RPJ技术赋能藤蔓机器人:实现局部刚度调控与刚柔并济
  • 2026莆田防水补漏避坑指南:卫生间/厨房/阳台/屋顶/地下室漏水检测维修全攻略,正规施工+透明报价+口碑榜靠谱服务商推荐 - 安佳防水
  • 基于LLM与记忆模块的对话信息增益自动评估系统实践