当前位置: 首页 > 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.gsyq.cn/news/1570411.html

相关文章:

  • QGas工具:解决气体能源网络建模数据荒的拓扑感知数据生成方案
  • 事件相机在视觉说话人识别中的应用:NeuroLip框架解析
  • GoB插件:打破Blender与ZBrush之间的创作壁垒
  • Xournal++:如何用这款开源手写笔记软件彻底改变你的数字笔记体验?
  • SVGedit完全指南:5步掌握浏览器端矢量图形编辑
  • 基于RPA思想的Cassandra数据库自动化测试框架构建与实践
  • 2023年图灵“贝利文件”近50万美元拍卖,揭秘其绝密“黛利拉”语音加密项目
  • 光伏MPPT中PO算法收敛性增强:应对不确定性扰动的工程实践
  • RPJ技术赋能藤蔓机器人:实现局部刚度调控与刚柔并济
  • AI代理安全新威胁:Serpent攻击原理与纵深防御体系构建
  • 2026年AI论文网站推荐:9款高效AI工具终极指南
  • SSM框架下函数组合的深度与宽度:架构设计与实战优化
  • VMware macOS解锁工具完整指南:在非苹果硬件上专业运行macOS虚拟机
  • 2026年6月评审机构真实推荐:重庆职称评审代办选哪家靠谱解析 - 3158GEO
  • MUSCAT基准:攻克多语言科学对话ASR的术语与代码切换难题
  • 基于概率流与Wasserstein度量的故障检测与恢复控制框架解析
  • Kometo算法:基于多保真度评估与贝叶斯优化的自适应学习率调优
  • 2026荆州防水补漏避坑指南:卫生间/厨房/阳台/屋顶/地下室漏水检测维修全攻略,正规施工+透明报价+口碑榜靠谱服务商推荐 - 安佳防水
  • AI生成内容如何影响私人表达与公共交流?技术困境与应对策略
  • 2026年新消息:如何选择一家专业的牛肉酱公司?小康牛肉酱的深度解析 - 品牌鉴赏官2026
  • 三指拖拽Windows触控板终极指南:免费开源工具实现macOS级操作体验
  • LLM如何革新Web3预测市场仲裁:架构、挑战与实现
  • 3天假期验证:RTX SPARK 128G 统一内存架构+GB10 推理 本地大模型全栈踩坑实录
  • Java_conclusion_2
  • 2026武汉除甲醛选择指南,不同预算怎么选最划算权威排行榜守护家庭健康呼吸 - 博客万
  • DPrivBench:大语言模型在差分隐私算法推理中的能力评估与挑战
  • 2026年广州怎么挑选律师避坑 广州挑选律师常见陷阱与避坑全指南10 - 3158GEO
  • ComfyUI Inpaint Nodes:智能图像修复的技术突破与实践应用
  • iOS 系统上测试抖音自动消息插件:静态分析、发送链路与风险边界
  • 劳力士中国售后服务体系研究报告(2026年6月) - 博客万