公司网站开发的国内外研究现状,中卫平面设计招聘,网站怎么做登陆,贵阳企业自助建站一、函数式接口
函数式接口是 Lambda 表达式和方法引用的容器#xff0c;是整个 Java 函数式编程的基础#xff0c;所有 Lambda 最终都要绑定到某个函数式接口的抽象方法上。
1. 核心定义
仅包含 一个抽象方法 的接口#xff08;可包含多个默认方法、静态方法、私有方法是整个 Java 函数式编程的基础所有 Lambda 最终都要绑定到某个函数式接口的抽象方法上。1. 核心定义仅包含一个抽象方法的接口可包含多个默认方法、静态方法、私有方法推荐用FunctionalInterface注解标记编译器会强制校验是否符合规范。2. 核心价值将「行为方法逻辑」抽象为接口类型让行为可以像变量一样被传递、赋值、作为方法参数/返回值。3. 常用内置函数式接口java.util.function 包接口类型核心方法入参/返回值典型用途消费型 Consumervoid accept(T t)入参 T无返回遍历集合、打印数据供给型 SupplierT get()无入参返回 T生成随机数、创建对象函数型 FunctionT,RR apply(T t)入参 T返回 R数据转换如字符串转数字断言型 Predicateboolean test(T t)入参 T返回布尔过滤集合、条件判断二元函数 BiFunctionT,U,RR apply(T t, U u)入参 TU返回 R双参数转换如两数运算4. 基础示例自定义使用// 自定义函数式接口单一抽象方法FunctionalInterfaceinterfaceMyFunction{Stringprocess(Strings);// 唯一抽象方法}publicclassFunctionalInterfaceDemo{publicstaticvoidmain(String[]args){// 给函数式接口赋值后续用Lambda实现MyFunctionupperCases-s.toUpperCase();MyFunctionaddSuffixs-s_suffix;// 调用抽象方法执行逻辑System.out.println(upperCase.process(hello));// HELLOSystem.out.println(addSuffix.process(test));// test_suffix}}二、Lambda 表达式Lambda 是函数式接口的简洁实例化方式替代冗长的匿名内部类本质是「一段可传递的代码块」。1. 核心语法(参数列表)-{方法体}简化规则核心减少冗余场景简化写法原始写法单参数s - s.toUpperCase()(String s) - { return s.toUpperCase(); }无参数() - Math.random()() - { return Math.random(); }单语句方法体(a, b) - a b(int a, int b) - { return a b; }多语句方法体(a, b) - { int c a*2; return c b; }必须带大括号和return2. 使用场景绑定函数式接口Lambda 不能单独存在必须绑定到「函数式接口的抽象方法」常见场景场景1赋值给函数式接口变量// 绑定Consumer接口ConsumerStringprints-System.out.println(s);print.accept(Lambda赋值示例);// 输出Lambda赋值示例// 绑定Predicate接口PredicateIntegerisOddnum-num%2!0;System.out.println(isOdd.test(5));// 输出true场景2作为方法参数行为参数化// 自定义方法接收函数式接口参数publicstaticTListTfilter(ListTlist,PredicateTcondition){ListTresultnewArrayList();for(Tt:list){if(condition.test(t)){result.add(t);}}returnresult;}// 调用传入Lambda作为过滤条件publicstaticvoidmain(String[]args){ListIntegernumsArrays.asList(1,2,3,4,5);// 过滤偶数ListIntegerevensfilter(nums,num-num%20);System.out.println(evens);// 输出[2,4]}3. 关键注意点Lambda 可捕获外部变量但变量必须是final或「有效 final」未显式声明 final但从未重新赋值Lambda 没有自己的thisthis指向外部类的对象编译期会将 Lambda 转换为函数式接口的匿名实现类运行期优化为 invokedynamic 指令。三、方法引用方法引用是 Lambda 的简化写法当 Lambda 体仅调用一个已有方法时可用「方法引用」替代让代码更简洁。1. 语法格式方法引用类型语法等效 Lambda 示例静态方法引用类名::静态方法名Integer::sum→(a,b) - Integer.sum(a,b)实例方法引用对象对象名::实例方法名str::toUpperCase→() - str.toUpperCase()实例方法引用类类名::实例方法名String::length→s - s.length()构造器引用类名::newArrayList::new→() - new ArrayList()2. 实战示例publicclassMethodReferenceDemo{publicstaticvoidmain(String[]args){// 1. 静态方法引用Integer::sumBinaryOperatorIntegersumInteger::sum;System.out.println(sum.apply(10,20));// 30// 2. 实例方法引用对象自定义字符串对象的toUpperCaseStringstrhello;SupplierStringupperCasestr::toUpperCase;System.out.println(upperCase.get());// HELLO// 3. 实例方法引用类String::lengthFunctionString,IntegerstrLengthString::length;System.out.println(strLength.apply(test));// 4// 4. 构造器引用ArrayList::newSupplierListStringlistSupplierArrayList::new;ListStringlistlistSupplier.get();list.add(a);System.out.println(list);// [a]}}3. 使用技巧方法引用的参数列表、返回值必须和绑定的函数式接口抽象方法完全匹配优先使用方法引用替代简单 Lambda提升代码可读性如 Stream 操作中。四、Stream 流函数式集合操作Stream 是 Java 提供的「函数式集合处理工具」基于 Lambda 和函数式接口实现支持「管道式」数据处理替代传统的 for 循环核心是「声明式编程」关注做什么而非怎么做。1. Stream 核心特性不存储数据仅处理数据源集合、数组等不修改原数据惰性求值中间操作如 filter、map仅记录逻辑终端操作如 forEach、collect才触发计算可并行通过parallelStream()实现并行处理简化多线程编程一次性流只能被消费一次再次使用需重新创建。2. 核心操作分类操作类型常用方法特点中间操作filter、map、distinct、sorted、limit返回 Stream可链式调用惰性执行终端操作forEach、collect、reduce、count、anyMatch返回非 Stream 结果触发计算3. 实战示例核心场景importjava.util.Arrays;importjava.util.List;importjava.util.Map;importjava.util.stream.Collectors;publicclassStreamDemo{// 定义测试实体类staticclassUser{privateStringname;privateintage;privateStringcity;publicUser(Stringname,intage,Stringcity){this.namename;this.ageage;this.citycity;}// 省略getter/setterpublicStringgetName(){returnname;}publicintgetAge(){returnage;}publicStringgetCity(){returncity;}}publicstaticvoidmain(String[]args){ListUserusersArrays.asList(newUser(Alice,22,Beijing),newUser(Bob,28,Shanghai),newUser(Charlie,22,Beijing),newUser(David,30,Shanghai));// 场景1过滤映射 → 获取北京22岁用户的姓名ListStringnamesusers.stream().filter(u-u.getAge()22Beijing.equals(u.getCity()))// 中间操作.map(User::getName)// 方法引用简化Lambda.collect(Collectors.toList());// 终端操作System.out.println(names);// [Alice, Charlie]// 场景2分组 → 按城市分组用户MapString,ListUsergroupByCityusers.stream().collect(Collectors.groupingBy(User::getCity));System.out.println(groupByCity);// {Beijing[Alice, Charlie], Shanghai[Bob, David]}// 场景3归约 → 计算所有用户的年龄总和inttotalAgeusers.stream().mapToInt(User::getAge)// 避免装箱提升性能.sum();// 终端操作System.out.println(totalAge);// 102// 场景4并行流 → 大数据量处理自动多线程longcountusers.parallelStream().filter(u-u.getAge()25).count();System.out.println(count);// 2}}4. 高频技巧基本类型流IntStream/LongStream/DoubleStream避免自动装箱/拆箱提升性能Optional结合 Stream处理可能为空的结果如findFirst()返回OptionalUsercollect()是最灵活的终端操作支持转集合、分组、拼接字符串Collectors.joining()等。五、核心总结函数式接口是基础定义了「行为的类型」是 Lambda 和方法引用的「载体」Lambda 表达式是函数式接口的「简洁实现」替代匿名内部类直接表达行为逻辑方法引用简化Lambda 进一步简化仅调用单个方法的 LambdaStream 流是函数式接口Lambda 的「实战场景」通过接收函数式接口参数如 filter 接收 Predicate实现声明式集合处理。六、避坑Stream 不要滥用小数据量场景下传统 for 循环可能比 Stream 更快无线程开销Lambda 不要写太复杂复杂逻辑拆分为方法用方法引用替代提升可读性并行流注意线程安全数据源若为线程不安全的集合如 ArrayList并行流处理时需注意函数式接口必须满足单一抽象方法用FunctionalInterface注解强制校验避免后续误加抽象方法。实战练习需求从员工列表中筛选出「部门为研发、年龄30岁」的员工按薪资降序排序最终获取他们的姓名和薪资格式姓名-薪资拼接成字符串。// 自行实现以下逻辑检验掌握程度ListEmployeeemployees// 初始化员工列表Stringresultemployees.stream().filter(/* 研发部门年龄30 */).sorted(/* 薪资降序 */).map(/* 转换为 姓名-薪资 字符串 */).collect(/* 拼接为逗号分隔的字符串 */);参考答案Stringresultemployees.stream().filter(e-研发.equals(e.getDept())e.getAge()30).sorted((e1,e2)-Double.compare(e2.getSalary(),e1.getSalary())).map(e-e.getName()-e.getSalary()).collect(Collectors.joining(,));