资讯动态

四大函数式接口:断真假/变数据/只动手/只供货,怎么拼流水线

发布时间:2026/10/24 5:41:14 来源:尧图企业网站定制
系列Lambda 函数式实战精通营 · 作者鱼宵配套课程仓库https://gitee.com/j67mk2/lambda-journey 第 2 课先看一个每天都在发生的现场领导让你把高薪研发部员工做成一张报表筛出研发部且月薪 ≥15000 的拼成一行字打出来。第一次写代码的人会这样for(Employeee:team){if(e.dept().equals(研发)e.salary()15000){// 条件写死在循环里System.out.println( [报表] ★e.name()研发部e.salary()元/月★);}}代码不多但问题藏在后面明天要改成筛测试部后天要筛行政部且工资 5000 以上再后天要在打印前加个通知动作——每次都要动这段循环。条件、转换、打印全焊死在一起改一处动全身。要是能把校验、转换、消费拆成三段每段独立换——这就是本文要讲的JDK 预置的四大函数式接口 组合方法。学完本文你能回答Predicate、Function、Consumer、Supplier 分别管什么andThen 和 compose 有什么区别、谁先算谁为什么说函数式接口可以像乐高一样拼装一句话原理四个接口各管一段组合方法把它们拼成流水线先摆结论PredicateT断真假。抽象方法boolean test(T t)——传一个东西进去回答满不满足条件只还 true/falseFunctionT,R变数据。抽象方法R apply(T t)——传一个类型进去还回来另一个类型ConsumerT只动手。抽象方法void accept(T t)——传一个东西进去做一件事打印/落库/发通知什么都不还SupplierT只供货。抽象方法T get()——不给它任何输入它负责造一个出来。组合方法default 方法能把小函数拼成大函数Predicate有and相当于 、or相当于 ||、negate相当于 !Function有andThen、composeConsumer有andThen。类比乐高积木。单个积木单个函数只能干一件小事凹凸卡扣一拼组合方法就能拼出城堡流水线。完整可运行代码一条员工报表流水线直接复制就能跑JDK 21packagecom.lambda.lesson02;importjava.util.List;importjava.util.function.Consumer;importjava.util.function.Function;importjava.util.function.Predicate;importjava.util.function.Supplier;publicclassMain{/** 员工姓名 年龄 月薪 部门 */recordEmployee(Stringname,intage,intsalary,Stringdept){}publicstaticvoidmain(String[]args){System.out.println( 一、Predicate断真假test / and / or / negate );PredicateIntegeradultage-age18;// 满 18 岁PredicateIntegerretiredage-age60;// 满 60 岁System.out.println(20 岁成年adult.test(20));// trueSystem.out.println(20 岁退休retired.test(20));// false// and两个条件都要满足相当于 negate取反相当于 !PredicateIntegermiddleAgeadult.and(age-age60);// 成年但没退休 中年System.out.println(40 岁算中年middleAge.test(40));// trueSystem.out.println(70 岁算中年middleAge.test(70));// falseSystem.out.println(70 岁退休retired.test(70));// trueSystem.out.println(40 岁没退休retired.negate().test(40));// true// or两个条件满足一个就行相当于 ||PredicateIntegernotCareerretired.or(age-age22);System.out.println(19 岁还算职业期notCareer.test(19));// trueSystem.out.println(35 岁还算职业期notCareer.test(35));// falseSystem.out.println();System.out.println( 二、Function变数据apply / andThen / compose );FunctionInteger,Integerplus2x-x2;// 加 2FunctionInteger,Integertimes3x-x*3;// 乘 3System.out.println(plus2.apply(5) plus2.apply(5));// 7// andThen先算自己再拿结果接着算下一个——f.andThen(g) 先 f 后 gFunctionInteger,Integerplus2ThenTimes3plus2.andThen(times3);System.out.println((52)*3 plus2ThenTimes3.apply(5));// 21// compose先算下一个再拿结果算自己——f.compose(g) 先 g 后 fFunctionInteger,Integertimes3AfterPlus2plus2.compose(times3);System.out.println((5*3)2 times3AfterPlus2.apply(5));// 17System.out.println();System.out.println( 三、Consumer只动手accept / andThen );ConsumerStringprintBoxs-System.out.println( [盒装] s);ConsumerStringprintStars-System.out.println( [星标] s);printBox.accept(第一份);// andThen把两个 Consumer 串成先做 A 再做 BConsumerStringboxThenStarprintBox.andThen(printStar);System.out.println(组合 Consumer 处理\第二份\);boxThenStar.accept(第二份);System.out.println();System.out.println( 四、Supplier只供货get );SupplierStringdefaultTitle()-未命名文档-System.currentTimeMillis()%100000;SupplierIntegerzero()-0;System.out.println(默认标题defaultTitle.get());System.out.println(兜底数字zero.get());System.out.println();System.out.println( 五、综合员工报表流水线供给→校验→转换→消费 );// 四个接口串成流水线Supplier 供货Predicate 校验Function 转换Consumer 消费SupplierListEmployeesupplyTeam()-List.of(newEmployee(张三,28,18000,研发),newEmployee(李四,32,12000,测试),newEmployee(王五,26,23000,研发),newEmployee(赵六,45,9000,行政));// 校验研发部 且 月薪 15000PredicateEmployeeisRnde-e.dept().equals(研发);PredicateEmployeewellPaide-e.salary()15000;PredicateEmployeetargetisRnd.and(wellPaid);// 转换员工 → 一行报表文字再 andThen 给名字加星标FunctionEmployee,StringtoLinee-e.name()e.dept()部e.salary()元/月;FunctionString,StringstarNameline-★line★;FunctionEmployee,StringtoReporttoLine.andThen(starName);// 消费打印报表行ConsumerStringreportOutline-System.out.println( [报表] line);System.out.println(开始生成高薪研发名单);intcount0;for(Employeee:supplyTeam.get()){// Supplier.get() 供货if(target.test(e)){// Predicate.test() 校验StringlinetoReport.apply(e);// Function.apply() 转换reportOut.accept(line);// Consumer.accept() 消费count;}}System.out.println(共筛出 count 人张三、王五是研发且高薪李四在测试部不沾边赵六是行政部且工资只有 9000);}}真实运行输出本机 JDK 24.0.1 实测 一、Predicate断真假test / and / or / negate 20 岁成年true 20 岁退休false 40 岁算中年true 70 岁算中年false 70 岁退休true 40 岁没退休true 19 岁还算职业期true 35 岁还算职业期false 二、Function变数据apply / andThen / compose plus2.apply(5) 7 (52)*3 21 (5*3)2 17 三、Consumer只动手accept / andThen [盒装] 第一份 组合 Consumer 处理第二份 [盒装] 第二份 [星标] 第二份 四、Supplier只供货get 默认标题未命名文档-35079 兜底数字0 五、综合员工报表流水线供给→校验→转换→消费 开始生成高薪研发名单 [报表] ★张三研发部18000元/月★ [报表] ★王五研发部23000元/月★ 共筛出 2 人张三、王五是研发且高薪李四在测试部不沾边赵六是行政部且工资只有 9000这段代码讲什么四个接口的定位背抽象方法签名就够了接口抽象方法一句话定位类比PredicateTboolean test(T t)断真假门卫查证件只回放行/不放行FunctionT,RR apply(T t)变数据食堂窗口递饭票出盖饭ConsumerTvoid accept(T t)只动手快递柜投递格口收走不还SupplierTT get()只供货自动售货机按一下吐一瓶水面试被问四大函数式接口先甩这张表再补例子。andThen vs compose执行顺序相反面试高频送命题FunctionInteger,Integerplus2x-x2;FunctionInteger,Integertimes3x-x*3;plus2.andThen(times3).apply(5)// (52)*3 21先 plus2 后 times3plus2.compose(times3).apply(5)// (5*3)2 17先 times3 后 plus2andThen先算自己结果然后给下一个。记从左往右读——plus2.andThen(times3)读成先加 2再乘 3compose先算下一个结果再垫脚给自己。记从右往左算——plus2.compose(times3)读成先乘 3再加 2两者互为镜像任何f.compose(g)都等于g.andThen(f)选哪个纯看读着顺。类比给奶茶加料。andThen 是先加珍珠再加奶盖compose 是先加奶盖再加珍珠——加的料一样顺序不一样最后口味结果就不一样。组合方法不修改原函数而是返回新函数PredicateIntegermiddleAgeadult.and(age-age60);and内部大致是return t - test(t) other.test(t);——它返回的还是一个 lambda原adult纹丝不动新手常犯的错只写adult.and(...)不接返回值以为生效了——没接住返回值新函数就丢了。组合方法本质是帮你 new 一个组合后的 lambda必须接住返回值。流水线的价值四段独立换一段不动其他SupplierListEmployeesupplyTeam...// 供货换名单来源只改这PredicateEmployeetargetisRnd.and(wellPaid);// 校验换筛选条件只改这FunctionEmployee,StringtoReport...// 转换换输出格式只改这ConsumerStringreportOut...// 消费换去向打印/落库/通知只改这明天要把研发改成测试只动isRnd那一行后天要把名单从内存换成数据库只动supplyTeam那个 lambda每段能单独测、单独换谁也不知道别人的内部细节——这就是分工。 进阶深挖选学官方接口不止四个java.util.function包还有BiFunctionT,U,R两个输入、BiPredicate、BiConsumer、UnaryOperatorFunctionT,T 特例、BinaryOperator两个 T 进一个 T 出还有避免装箱的原始类型版本IntPredicate、LongFunction、DoubleSupplier第 9 课讲性能时你就知道为什么要专门为 int 开一套。组合方法是 default 方法的原因Java 8 为了给老接口加新方法又不破坏实现类的妥协——加了 default 方法老实现类不用改也能用新能力。设计模式视角andThen层层包装就像给奶茶加珍珠、加奶盖、加冰——每层都不改变奶茶本体只是在外面再套一层加工。调用时从最外层往里算和装饰器模式层层包装、层层委托是同一个思想。面试回答模板问andThen 和 compose 有什么区别一句话结论两者都是 Function 的组合方法但执行顺序相反。展开 1~2 句f.andThen(g)是先执行 f 再把结果交给 g即g(f(x))f.compose(g)是先执行 g 再交给 f即f(g(x))。拿plus2和times3代 5 手算andThen 得 21compose 得 17。收一句拼数据处理流水线时用 andThen 读着最顺和一步接一步的写法一致指向课程 lesson-02 §8。问Predicate 和 Function 分不清怎么办一句话结论有返回值的是 Function没有的是 ConsumerPredicate 是返回 boolean 的 Function。展开Predicate.test只回答满不满足条件booleanFunction.apply把输入变成另一个类型T→RConsumer.accept做一件事什么都不还Supplier.get连入参都没有、只负责造东西指向课程 lesson-02 §3。总结表坑 → 原因 → 解法坑原因解法四个接口记混签名分不清背有返回是 Function无返回是 Consumer只答真假是 Predicate只出不进是 SupplierandThen/compose 顺序写反把 andThen 当成先乘后加代入具体数字手算5 代进去21 和 17 谁是哪个立刻清楚以为组合方法修改了原函数忽略返回新函数f.andThen(g)必须接住返回值原f纹丝不动a.or(b).and(c)优先级想当然组合按调用顺序从左往右粘a.or(b).and(c)是(a‖b)c想要别的逻辑就用变量分层JDK 低于 21版本不满足先java -version确认 21挑战题答案都在课程源码里⭐ 把员工名单扩到 6 个人工资阈值从 15000 改成 20000重新跑看报表剩几行。⭐⭐ 把isRnd.and(wellPaid)改成isRnd.or(wellPaid)猜一下输出会变几行跑起来验证。⭐⭐ 用negate()写一条规则筛出不满足’研发且高薪’的员工打印被刷掉的人是谁。⭐⭐⭐ 加一段发通知流程再定义一个ConsumerEmployee打印通知已发张三用 andThen 把打印报表行和发通知串起来让每个被选中的员工同时触发两个动作。源码在哪怎么跑完整代码在lambda-journey 课程第 2 课gitclone https://gitee.com/j67mk2/lambda-journey.gitcdlambda-journey/lesson-02 mvn-qcleaninstall-DskipTestsjava-cptarget/classes com.lambda.lesson02.Main第 2 课四大接口 组合方法全解 5 道面试题 课后作业 5 道本文属于Lambda 函数式实战精通营系列10 课L1 世界观 →L2 四大接口→ L3 方法引用 → L4 闭包 → L5 异常 → L6 重构 → L7/L8 Lambda×Stream 组合 → L9 性能 → L10 企业级收官。下一篇方法引用四种形态——::到底能引用哪四种方法构造器怎么用::引出来。跑出来的输出和我不一样把现象发评论区一起查。觉得有用就收藏一下追更这个系列。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑