Java 8+ 特性(Lambda表达式、Stream API、Optional类等)必会知识汇总
目录:
- 🧠 一、Lambda 表达式
- 🧩 二、Stream API
-
- 1. 核心概念
- 2. 创建 Stream
- 3. 中间操作(Intermediate)
- 4. 终端操作(Terminal)
- 5. 示例
- 6. 注意事项
- 🧱 三、Optional 类
-
- 1. 核心概念
- 2. 常见方法
- 3. 示例
- 4. 注意事项
- 📌 四、接口默认方法与静态方法
-
- 1. 默认方法(Default Method)
- 2. 静态方法(Static Method)
- 3. 使用场景
- 📦 五、新日期时间 API(java.time)**
-
- 1. 核心类
- 2. 示例
- 3. 优点
- 🧩 六、常用函数式接口
- 📊 七、常见面试题及答案
-
- 1. Lambda 表达式与匿名内部类的区别?
- 2. Stream 的 map 和 flatMap 的区别?
- 3. Optional 的 orElse() 和 orElseGet() 的区别?
- 4. Collectors 常用方法?
- 5. Stream 的 filter 和 map 的执行顺序?
- ✅ 八、总结:Java 8+ 核心特性
- 📚 九、推荐学习资料
- 📄 十、完整代码示例(含 Stream + Optional + Lambda)
🧠 一、Lambda 表达式
1. 基本概念
- 作用:简化匿名内部类的写法,支持函数式编程。
- 语法:
(parameters) -> expression
(parameters) -> { statements; }
2. 使用场景
- 替代匿名内部类(如 Runnable、Comparator)。
- 简化集合操作(结合 Stream API 使用)。
3. 示例
// 传统匿名类new Thread(new Runnable() { public void run() { System.out.println(\"Hello\"); }}).start();
// Lambda 表达式new Thread(() -> System.out.println(\"Hello\")).start();
// 集合排序List<String> list = Arrays.asList(\"a\", \"b\", \"c\");list.sort((s1, s2) -> s1.compareTo(s2));
4. 函数式接口
- 定义:只有一个抽象方法的接口(可包含默认方法和静态方法)。
- 常见内置函数式接口:
- Consumer:消费型接口(无返回值)
- Function:函数型接口(输入 T,输出 R)
- Predicate:断言型接口(返回 boolean)
- Supplier:供给型接口(无输入,返回 T)
5. 方法引用
- 语法:
- 对象::实例方法
- 类::静态方法
- 类::实例方法(第一个参数是实例)
示例:
List<String> list = Arrays.asList(\"a\", \"b\", \"c\");list.forEach(System.out::println); // 对象::实例方法
🧩 二、Stream API
1. 核心概念
- 作用:对集合进行函数式操作(过滤、映射、聚合等)。
- 特点:链式调用、惰性求值、支持并行处理。
2. 创建 Stream
- 方式:
Stream<String> stream = list.stream(); // 从集合创建Stream<String> stream = Stream.of(\"a\", \"b\"); // 直接创建
3. 中间操作(Intermediate)
4. 终端操作(Terminal)
5. 示例
List<String> list = Arrays.asList(\"apple\", \"banana\", \"cherry\");// 过滤并收集List<String> filtered = list.stream() .filter(s -> s.startsWith(\"a\")) .collect(Collectors.toList());// 求和int sum = list.stream() .mapToInt(String::length) .sum();// 分组Map<Integer, List<String>> grouped = list.stream() .collect(Collectors.groupingBy(String::length));
6. 注意事项
- 不要用于小数据量:Stream 的性能优势在大数据量时更明显。
- 避免中间操作无终端操作:中间操作是惰性的,只有终端操作才会执行。
- 避免在 Stream 中修改外部变量:应使用不可变操作。
🧱 三、Optional 类
1. 核心概念
- 作用:避免空指针异(NullPointerException)。
- 使用场景:替代 null 检查,使代码更简洁。
2. 常见方法
3. 示例
String name = Optional.ofNullable(getName()) .orElse(\"Default\");// 避免嵌套 null 检查Optional<User> user = Optional.ofNullable(findUser());user.flatMap(User::getAddress) .ifPresent(System.out::println);
4. 注意事项
- 不要滥用 get():使用前必须调用 isPresent() 检查。
- 避免 Optional 作为类字段:可能导致序列化问题。
- 优先使用orElseGet() 而非 orElse():避免不必要的计算。
📌 四、接口默认方法与静态方法
1. 默认方法(Default Method)
- 作用:在接口中提供默认实现,避免接口升级时破坏实现类。
- 语法:
public interface MyInterface { default void defaultMethod() { System.out.println(\"Default Method\"); }}
2. 静态方法(Static Method)
- 作用:在接口中定义工具方法。
- 语法:
public interface MyInterface { static void staticMethod() { System.out.println(\"Static Method\"); }}
3. 使用场景
- 默认方法:为接口添加新方法时兼容旧实现类。
- 静态方法:提供与接口相关的工具方法(如 Comparator.naturalOrder())。
📦 五、新日期时间 API(java.time)**
1. 核心类
2. 示例
LocalDate today = LocalDate.now();LocalDate tomorrow = today.plusDays(1);LocalTime now = LocalTime.now();LocalTime twoHoursLater = now.plusHours(2);// 计算两个日期间隔Period period = LocalDate.of(2023, 10, 1).until(LocalDate.of(2023, 10, 10));System.out.println(period.get(ChronoUnit.DAYS)); // 输出 9
3. 优点
- 线程安全:java.util.Date 是可变对象,LocalDate 是不可变的。
- 更直观的 API:如 plusDays()、minusDays()。
🧩 六、常用函数式接口
📊 七、常见面试题及答案
1. Lambda 表达式与匿名内部类的区别?
- Lambda 表达式:只能用于函数式接口,语法更简洁。
- 匿名内部类:可以实现任意接口,语法冗长。
2. Stream 的 map 和 flatMap 的区别?
- map:将每个元素转换为新元素(如 Stream → Stream)。
- flatMap:将每个元素转换为一个流,然后扁平化为一个流(如 Stream → Stream)。
3. Optional 的 orElse() 和 orElseGet() 的区别?
- orElse(T):无论 Optional 是否为空,都会执行 T 的创建。
- orElseGet(Supplier):仅在 Optional 为空时才执行 Supplier。
4. Collectors 常用方法?
5. Stream 的 filter 和 map 的执行顺序?
- 顺序执行:先 filter 再 map,避免不必要的转换。
- 惰性求值:中间操作不会立即执行,终端操作触发处理。
✅ 八、总结:Java 8+ 核心特性
📚 九、推荐学习资料
- 《Java 8 实战》(Cay S. Horstmann)
- 《Java 9 并发编程实战》
- B站、慕课网、CSDN、知乎 等平台的 Java 8 教程
- Java 官方文档:https://docs.oracle.com/javase/8/docs/
📄 十、完整代码示例(含 Stream + Optional + Lambda)
List<User> users = Arrays.asList( new User(\"Alice\", 25), new User(\"Bob\", 30), new User(\"Charlie\", 25));// 过滤年龄为25的用户,按姓名排序List<String> names = users.stream() .filter(user -> user.getAge() == 25) .sorted(Comparator.comparing(User::getName)) .map(User::getName) .collect(Collectors.toList());// 使用 Optional 避免 nullOptional<User> userOpt = Optional.ofNullable(findUser(\"Alice\"));userOpt.ifPresent(user -> System.out.println(user.getName()));// 分组(按年龄)Map<Integer, List<User>> groupedByAge = users.stream() .collect(Collectors.groupingBy(User::getAge));