这三个是 Java 8 面试里最常被放在一起问的,可以按“Lambda 写行为、Stream 处理集合、Optional 处理空值”来记。
1. Lambda 表达式
作用:简化匿名内部类,让“一段行为”可以像参数一样传进去。
// 传统写法newThread(newRunnable(){@Overridepublicvoidrun(){System.out.println("hello");}}).start();// Lambda 写法newThread(()->System.out.println("hello")).start();关键点:
- 只能用于函数式接口,也就是只有一个抽象方法的接口。
- 常用内置接口:
Predicate<T>:接收参数,返回boolean,比如x -> x > 10Function<T,R>:接收 T,返回 R,比如s -> s.length()Consumer<T>:接收参数,无返回值,比如s -> System.out.println(s)Supplier<T>:无参数,返回 T,比如() -> new User()
- Lambda 捕获的外部局部变量必须是
final或“事实上不可变”。
面试可以答:Lambda 本质是函数式接口的实例,用来简化匿名内部类。
2. Stream 流
作用:对集合做过滤、转换、排序、统计、分组,替代繁琐的for循环。
List<String>names=users.stream().filter(u->u.getAge()>18).map(User::getName).sorted().collect(Collectors.toList());三个阶段:
- 创建流:
list.stream()、Stream.of() - 中间操作:
filter、map、flatMap、sorted、distinct、limit、skip - 终止操作:
forEach、collect、count、reduce、max、min、anyMatch
中间操作是“加工”,终端操作是“出锅”。
filter、map、flatMap、sorted 都在加工;collect、count、forEach、findFirst 就是出锅拿结果
特点:
- Stream不存储数据,只是对数据源做计算。
- 中间操作是惰性求值,只有遇到终止操作才会真正执行。
- Stream不会修改原集合。
- Stream只能消费一次,用完不能再次使用。
面试常问:map和flatMap区别?map是一对一转换;flatMap是一对多再扁平化,比如List<List<String>>转成List<String>。
3. Optional
作用:优雅处理可能为null的值,减少if (obj != null)。
Optional<User>userOpt=Optional.ofNullable(user);Stringname=userOpt.map(User::getName).orElse("未知");// 通常写法如下,少一个变量命名Stringname=Optional.ofNullable(user).map(User::getName).orElse("未知名字");常用方法:
Optional.of(value):值不能为null,否则抛异常Optional.ofNullable(value):允许nullisPresent():判断是否有值ifPresent():有值才执行orElse():为空给默认值orElseGet():为空时执行逻辑生成默认值orElseThrow():为空抛异常
面试坑点:orElse()和orElseGet()区别?orElse()无论是否为空都会执行;orElseGet()只有为空时才执行。所以orElseGet()更适合生成默认值。
面试一句话总结
Lambda 简化匿名内部类,Stream 做集合流式处理,Optional 用来避免空指针。这三个经常一起出现,最好各准备一个代码示例。
需要我详细讲讲Stream中map和flatMap的区别,并写个代码示例帮你理解吗?
你前面已经基本掌握了这三个东西,现在可以按“Lambda 写行为,Stream 处理集合,Optional 处理空值”来记。
速记版
| 概念 | 作用 | 常见写法 |
|---|---|---|
| Lambda | 简化函数式接口实现 | (x) -> x > 10 |
| Stream | 链式处理集合 | filter / map / collect |
| Optional | 避免空指针 | map / orElse / orElseThrow |
组合示例
Optional<String>name=users.stream().filter(u->u.getAge()>18).map(User::getName).findFirst();Stringresult=name.orElse("未知用户");这里三个都用上了:
u -> u.getAge() > 18是Lambda;stream / filter / map / findFirst是Stream;findFirst返回Optional,用orElse兜底是Optional。
面试高频坑点
filter是中间操作,不会立即执行;collect / count / forEach是终止操作,才会真正触发计算。- Stream 只能消费一次,不能重复使用。
map是一对一转换;flatMap是一对多再扁平化。Optional.of()传 null 会抛异常;Optional.ofNullable()才允许 null。orElse()不管有没有值都会执行;orElseGet()只有为空时才执行。- Lambda 只能用于函数式接口,也就是只有一个抽象方法的接口。
如果你是想练代码题,可以重点练这几类:集合过滤排序、去重统计、分组、转 Map、Optional 链式判空。需要的话我可以直接出几道带答案的练习题。