function接口定义映射逻辑契约,通过方法引用(如student::getname)或lambda表达式实现精准、类型安全的属性提取,支持andthen链式转换,需避免null调用、泛型不匹配等陷阱。

Function 接口本身不“实现”映射,而是**定义映射逻辑的契约**——它让你用简洁、类型安全的方式描述“从对象中取哪个属性”,再交由 Stream.map 或其他上下文执行。精准映射的关键,在于写对 Function 实例,而非改造接口本身。
用方法引用直接提取属性值
这是最常用、最安全的方式。只要属性有标准 getter,就能用 Class::getPropertyName 构造 Function。
- 例如 Student 类有 public String getName(),则 Function
f = Student::getName - 调用 f.apply(student) 就返回 student.getName() 的结果,类型明确、无反射开销、编译期检查
- 支持链式提取:Function
fullName = s -> s.getFirstName() + " " + s.getLastName()
用 Lambda 表达式处理复杂逻辑
当属性需计算、拼接、空值判断或格式转换时,Lambda 比方法引用更灵活。
- 比如提取带默认值的邮箱:Function
emailOrUnknown = s -> Optional.ofNullable(s.getEmail()).orElse("unknown@example.com") - 或组合多个字段生成标识符:Function
idKey = s -> s.getId() + "-" + s.getDepartment().getCode() - 注意:Lambda 体内不能抛出受检异常;若需处理 IOException 等,需自行包装或使用 try-catch
结合 andThen 实现多步转换
andThen 不是“多次 map”,而是把一次映射拆成可复用的原子步骤,提升可读性和复用性。
- 先取 name,再转大写再截取前10位:Function
name = Student::getName; Function upperAndTrunc = s -> s.toUpperCase().substring(0, Math.min(10, s.length())); Function finalMapper = name.andThen(upperAndTrunc) - 这样 name 和 upperAndTrunc 可单独测试、复用,也避免在 map 中堆砌长表达式
- compose 适合前置预处理(如先标准化输入),但日常属性提取中 andThen 更直观
避免常见陷阱
精准映射失效,往往不是 Function 写错了,而是上下文或数据出了问题。
- 不要用 Function 提取 null 对象的属性:student 为 null 时,Student::getName 会抛 NullPointerException —— 应提前 filter 或用 Optional 包装
- 不要混淆 Function 和 Supplier:Supplier
是“无参生成字符串”,不能用于 map(Student::getName) 这类场景 - 泛型必须匹配:Function
getId = Student::getId 是合法的;若写成 Function
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











