当前位置: 首页 > news >正文

Java 8核心特性详解:从Lambda到Stream的革命性升级

Java 8核心特性详解:从Lambda到Stream的革命性升级

🎬 开篇故事:当Java遇见函数式编程

想象一下,如果编程语言是一个魔法世界,那么Java 8就像是哈利·波特获得魔法棒的那一刻。在此之前,Java程序员就像麻瓜一样,只能用繁琐的匿名内部类来"施展魔法";而Java 8的到来,就像是霍格沃茨向Java世界敞开了大门,Lambda表达式就是那根魔法棒,让我们能够优雅地挥舞代码,施展函数式编程的魔法!

🚀 为什么这次升级如此重要?

2014年3月18日,一个值得载入Java史册的日子。Oracle发布了Java SE 8,这不仅仅是一次版本更新,更是一次编程范式的革命

🎭 从"怎么做"到"做什么"的思维转变

// 传统思维:告诉计算机怎么做(How)
List<String> result = new ArrayList<>();
for (Person person : people) {if (person.getAge() > 18) {result.add(person.getName().toUpperCase());}
}// 函数式思维:告诉计算机做什么(What)
List<String> result = people.stream().filter(person -> person.getAge() > 18).map(person -> person.getName().toUpperCase()).collect(toList());

⚡ 多核时代的性能觉醒

在多核CPU普及的今天,Java 8让并行处理变得像呼吸一样自然:

// 串行处理:单核苦苦支撑
long count = bigList.stream().filter(expensiveOperation).count();// 并行处理:多核协同作战
long count = bigList.parallelStream().filter(expensiveOperation).count();

🛡️ 与空指针异常的终极决战

// 过去:如履薄冰的null检查
String city = null;
if (user != null) {Address address = user.getAddress();if (address != null) {city = address.getCity();}
}// 现在:优雅的Optional链式调用
String city = Optional.ofNullable(user).map(User::getAddress).map(Address::getCity).orElse("Unknown");

🎯 深度学习之旅

本文不仅教你如何使用Java 8特性,更重要的是理解为什么这样设计底层如何实现何时使用以及性能影响

🧠 你将获得的思维升级

  • 💡 函数式思维 - 从命令式到声明式的思维转变
  • 🔍 性能洞察 - 理解Lambda、Stream的内存模型和性能特征
  • 🏗️ 架构视野 - 学会用函数式编程构建更优雅的系统
  • 🎨 代码美学 - 写出既高效又优雅的代码

📚 文章结构说明

我们采用3W学习法来组织每个特性:

  • What(是什么) - 概念定义与基本语法
  • Why(为什么) - 设计动机与解决的问题
  • How(怎么做) - 实战应用与深度解析

目录

  1. Lambda表达式
  2. 函数式接口
  3. Stream API
  4. Optional类
  5. 新的日期时间API
  6. 接口默认方法
  7. 方法引用
  8. CompletableFuture
  9. Nashorn JavaScript引擎
  10. 总结与最佳实践

环境准备

本文所有示例代码基于Java 8环境,建议使用JDK 1.8.0_xxx版本。


1. Lambda表达式 🎭

💡 思考题:为什么Lambda表达式被称为"匿名函数"?它们真的是函数吗?

答案将在本章末尾揭晓!

1.1 是什么(What)

🎬 场景设想:你是一家咖啡店的老板,需要根据不同条件筛选客户。传统方式就像是为每种筛选条件都雇佣一个专门的员工,而Lambda表达式就像是培训一个多才多艺的员工,可以随时改变筛选规则!

Lambda表达式本质上是一段可以传递的代码,它代表了一个函数接口的简洁实现。

🔍 深度解析:Lambda的本质
// 🎯 Lambda并不是真正的"函数",而是函数接口的语法糖
Runnable task = () -> System.out.println("Hello Lambda!");// 编译器实际上会将其转换为类似这样:
Runnable task = new Runnable() {@Overridepublic void run() {System.out.println("Hello Lambda!");}
};
📝 语法精要
// 🏗️ Lambda架构:(参数列表) -> {函数体}
//                  ↑           ↑
//                输入        输出/操作// 🔧 类型推断:让编译器成为你的助手
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");// 完整写法(啰嗦但清晰)
names.forEach((String name) -> System.out.println(name));// 类型推断(简洁而优雅)
names.forEach(name -> System.out.println(name));// 方法引用(极致简洁)
names.forEach(System.out::println);
🧪 Lambda实验室:语法变化
public class LambdaEvolution {public static void main(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);// 🔬 实验1:无参数LambdaRunnable printer = () -> System.out.println("无参数Lambda执行!");// 🔬 实验2:单参数Lambda(可省略括号)numbers.forEach(n -> System.out.println("数字:" + n));// 🔬 实验3:多参数LambdaBinaryOperator<Integer> adder = (a, b) -> a + b;// 🔬 实验4:多行LambdaPredicate<Integer> complexChecker = n -> {System.out.println("检查数字:" + n);boolean result = n > 0 && n % 2 == 0;System.out.println("结果:" + result);return result;};// 🎯 让我们看看实际效果printer.run();System.out.println("3 + 5 = " + adder.apply(3, 5));numbers.stream().filter(complexChecker).forEach(System.out::println);}
}

1.2 为什么(Why)

🕰️ 历史的痛点:匿名内部类的困扰

想象一下,在Lambda之前的Java世界,传递一个简单的行为需要多少代码:

// 😵 2013年的Java程序员日常:为了传递一个简单行为写这么多代码
button.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {System.out.println("按钮被点击了!");}
});// 😨 更痛苦的例子:对列表进行简单操作
Collections.sort(people, new Comparator<Person>() {@Overridepublic int compare(Person p1, Person p2) {return p1.getName().compareTo(p2.getName());}
});
💡 Lambda带来的设计哲学转变

Java 8的Lambda表达式不仅仅是语法糖,它背后体现了深刻的设计思想:

  1. 📈 抽象层次的提升

    • 从"对象"抽象提升到"行为"抽象
    • 让代码更接近问题域的表达
  2. 🎯 声明式编程的引入

    • 专注于"做什么"而不是"怎么做"
    • 让代码意图更加清晰
  3. ⚡ 性能优化的可能性

    • 为编译器优化创造空间
    • 支持懒求值和并行化
🔬 深层原理:为什么Lambda这么高效?
// 🎭 秘密揭露:Lambda的性能魔法
// Lambda不是通过匿名内部类实现的!而是通过invokedynamic指令// 传统匿名内部类:每次都创建新的Class文件
Runnable r1 = new Runnable() { public void run() { System.out.println("传统方式"); } 
};// Lambda表达式:使用invokedynamic,运行时动态链接
Runnable r2 = () -> System.out.println("Lambda方式");// 🔍 编译后的字节码差异:
// 匿名内部类:产生额外的.class文件,增加内存开销
// Lambda:使用MethodHandle,更高效的方法调用
🎯 解决的核心问题
  • 🎨 表达力危机:让代码表达更贴近自然语言
  • 🏗️ 抽象不足:提供更高层次的抽象机制
  • ⚡ 性能瓶颈:避免匿名内部类的额外开销
  • 🔄 并发困难:为并行处理奠定语法基础

1.3 怎么做(How)

🚀 实战演练:从入门到精通

让我们通过一系列渐进式的实战案例,掌握Lambda表达式的精髓!

🎬 场景1:智能咖啡店的客户管理系统
import java.util.*;
import java.util.function.*;
import java.util.stream.Collectors;public class LambdaDemo {public static void main(String[] args) {List<Customer> customers = getCustomers(); // 假设有客户数据// 🎯 Lambda实战案例// 1. 基础过滤Predicate<Customer> isGold = c -> "GOLD".equals(c.getLevel());customers.stream().filter(isGold).forEach(System.out::println);// 2. 链式操作customers.stream().filter(c -> c.getAge() < 30).filter(c -> c.getSpent() > 1000).map(c -> c.getName() + " - VIP客户").forEach(System.out::println);// 3. 自定义排序customers.stream().sorted((c1, c2) -> Double.compare(c2.getSpent(), c1.getSpent())).limit(3).forEach(System.out::println);}
}
🎮 互动挑战:Lambda进阶技巧
public class LambdaAdvancedTricks {public static void main(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);// 🧩 挑战1:闭包的力量(Lambda捕获外部变量)int multiplier = 3; // effectively finalList<Integer> multiplied = numbers.stream().map(n -> n * multiplier) // 闭包捕获multiplier.collect(Collectors.toList());System.out.println("乘以3的结果: " + multiplied);// 🎯 挑战2:组合Lambda(函数式编程的精髓)Predicate<Integer> isEven = n -> n % 2 == 0;Predicate<Integer> isGreaterThan5 = n -> n > 5;Predicate<Integer> complexCondition = isEven.and(isGreaterThan5);System.out.println("偶数且大于5: " + numbers.stream().filter(complexCondition).collect(Collectors.toList()));// 🚀 挑战3:递归Lambda(是的,Lambda可以递归!)UnaryOperator<Integer> factorial = new UnaryOperator<Integer>() {@Overridepublic Integer apply(Integer n) {return n <= 1 ? 1 : n * this.apply(n - 1);}};System.out.println("5的阶乘: " + factorial.apply(5));}
}
Java 8前后的对比

对比1:事件处理

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;public class EventHandlingComparison {public static void main(String[] args) {JButton button = new JButton("点击我");// Java 8之前:匿名内部类button.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {System.out.println("按钮被点击了!");}});// Java 8:Lambda表达式button.addActionListener(e -> System.out.println("按钮被点击了!"));// 方法引用(需要匹配的方法签名)button.addActionListener(EventHandlingComparison::printClickMessage);}private static void printClickMessage(ActionEvent e) {System.out.println("按钮被点击了!");}
}

对比2:线程创建

public class ThreadCreationComparison {public static void main(String[] args) {// Java 8之前:匿名内部类Thread oldThread = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("旧方式创建线程");}});// Java 8:Lambda表达式Thread newThread = new Thread(() -> System.out.println("Lambda创建线程"));oldThread.start();newThread.start();}
}

对比3:比较器实现

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;public class ComparatorComparison {public static void main(String[] args) {List<String> names = Arrays.asList("Charlie", "Alice", "David", "Bob");// Java 8之前:匿名内部类System.out.println("=== Java 8之前排序 ===");List<String> oldSorted = Arrays.asList("Charlie", "Alice", "David", "Bob");oldSorted.sort(new Comparator<String>() {@Overridepublic int compare(String s1, String s2) {return s1.compareTo(s2);}});System.out.println(oldSorted);// Java 8:Lambda表达式System.out.println("\n=== Java 8 Lambda排序 ===");List<String> newSorted = Arrays.asList("Charlie", "Alice", "David", "Bob");newSorted.sort((s1, s2) -> s1.compareTo(s2));System.out.println(newSorted);// 更简洁的写法System.out.println("\n=== 方法引用排序 ===");List<String> refSorted = Arrays.asList("Charlie", "Alice", "David", "Bob");refSorted.sort(String::compareTo);System.out.println(refSorted);}
}
🧠 深度思考:Lambda的设计智慧
💭 思考题答案揭晓

还记得开头的问题吗?为什么Lambda表达式被称为"匿名函数"?它们真的是函数吗?

答案:Lambda表达式被称为"匿名函数"是一种便于理解的说法,但在Java中它们本质上不是函数

// 🔍 真相大白:Lambda的真实身份
// Lambda表达式实际上是函数接口的实例,是对象,不是函数!Predicate<String> isEmpty = String::isEmpty;
// ↑ 这创建了一个Predicate对象,不是一个函数// 🎯 证据:Lambda有对象的特征
System.out.println(isEmpty.getClass().getName()); 
// 输出类似:com.example.Main$$Lambda$1/123456789
System.out.println(isEmpty.toString()); 
// 证明它是对象!
🔬 性能剖析:Lambda vs 匿名内部类
public class PerformanceComparison {public static void main(String[] args) {// 🏃‍♂️ 性能测试:创建1000万个实例long start, end;// 测试匿名内部类start = System.currentTimeMillis();for (int i = 0; i < 10_000_000; i++) {Runnable r = new Runnable() {@Override public void run() { /* do nothing */ }};}end = System.currentTimeMillis();System.out.println("匿名内部类耗时: " + (end - start) + "ms");// 测试Lambda表达式start = System.currentTimeMillis();for (int i = 0; i < 10_000_000; i++) {Runnable r = () -> { /* do nothing */ };}end = System.currentTimeMillis();System.out.println("Lambda表达式耗时: " + (end - start) + "ms");// 💡 结果:Lambda通常比匿名内部类快2-3倍!}
}
🎨 设计模式进化:Lambda如何改变经典模式
// 🏗️ 策略模式的Lambda进化
public class StrategyPatternEvolution {// 传统策略模式:需要定义接口和多个实现类interface PaymentStrategy {void pay(double amount);}static class CreditCardPayment implements PaymentStrategy {public void pay(double amount) { System.out.println("信用卡支付: " + amount); }}static class AlipayPayment implements PaymentStrategy {public void pay(double amount) { System.out.println("支付宝支付: " + amount); }}public static void main(String[] args) {// 🎭 Lambda让策略模式焕然一新Map<String, PaymentStrategy> strategies = new HashMap<>();// 不需要创建类,直接用Lambda定义策略!strategies.put("credit", amount -> System.out.println("信用卡支付: " + amount));strategies.put("alipay", amount -> System.out.println("支付宝支付: " + amount));strategies.put("wechat", amount -> System.out.println("微信支付: " + amount));// 🚀 动态策略选择strategies.get("alipay").pay(299.99);}
}

🎯 Lambda的本质改变:

  • 🎭 编程范式融合:将函数式编程优雅地融入面向对象体系
  • ⚡ 性能革命:通过invokedynamic实现更高效的方法调用
  • 🧠 思维升级:从"创建对象来执行行为"到"直接传递行为"
  • 🎨 设计简化:让经典设计模式更加轻量和灵活

2. 函数式接口 🎯

🎭 角色扮演:如果Lambda表达式是演员,那么函数式接口就是剧本!

每个Lambda表达式都需要一个"角色定义"来明确自己要扮演什么,而函数式接口就是这个角色的说明书。

2.1 是什么(What)

🎪 函数式接口的奇妙世界

想象一下,Java的接口原本是一个严肃的契约大厅,每个接口都要求实现者必须实现所有方法。然后Java 8带来了一个革命性的概念:单一职责接口

// 🎯 函数式接口的黄金法则:一个抽象方法
@FunctionalInterface
public interface Magic<T, R> {R cast(T input);  // 唯一的抽象方法 - 施展魔法// ✅ 可以有默认方法default void prepare() {System.out.println("准备施法...");}// ✅ 可以有静态方法static void study() {System.out.println("学习魔法理论...");}// ✅ 可以重写Object的方法@Overrideboolean equals(Object obj);
}
🔬 深度解析:@FunctionalInterface的魔力
// 🎭 幕后英雄:@FunctionalInterface注解
@FunctionalInterface
public interface Calculator {double calculate(double a, double b);// 🚫 编译错误!不能有第二个抽象方法// double anotherMethod(double x);
}// 🧪 实验:没有注解会怎样?
interface SilentCalculator {double calculate(double a, double b);// 依然是函数式接口,但没有编译时检查
}public class FunctionalInterfaceDemo {public static void main(String[] args) {// 🎯 Lambda表达式自动匹配函数式接口Calculator adder = (a, b) -> a + b;Calculator multiplier = (a, b) -> a * b;System.out.println("3 + 5 = " + adder.calculate(3, 5));System.out.println("3 × 5 = " + multiplier.calculate(3, 5));// 🎪 方法引用也能匹配Calculator maxFinder = Double::max;System.out.println("max(3, 5) = " + maxFinder.calculate(3, 5));}
}
🏗️ Java 8内置函数式接口宇宙图
// 🌟 四大天王:Java 8的核心函数式接口
import java.util.function.*;public class FunctionalInterfaceUniverse {public static void main(String[] args) {// 🎯 Predicate<T>: 判断者 - 输入T,输出booleanPredicate<String> isLongName = name -> name.length() > 5;System.out.println("Alice是长名字吗? " + isLongName.test("Alice"));// 🔄 Function<T,R>: 转换者 - 输入T,输出R  Function<String, Integer> nameLength = String::length;System.out.println("Alice名字长度: " + nameLength.apply("Alice"));// 🍽️ Consumer<T>: 消费者 - 输入T,无输出Consumer<String> printer = name -> System.out.println("Hello, " + name);printer.accept("World");// 🏭 Supplier<T>: 供应者 - 无输入,输出TSupplier<Double> randomSupplier = Math::random;System.out.println("随机数: " + randomSupplier.get());}
}

2.2 为什么(Why)

🎬 历史的呼唤:函数式接口的诞生背景

在Java 8之前,想要传递一个简单的行为是多么痛苦的事情:

// 😱 Java 7时代的噩梦:想要传递一个简单的比较逻辑
public interface StringComparator {int compare(String s1, String s2);
}public interface NumberFilter {boolean filter(Integer number);
}public interface TextProcessor {String process(String text);
}// 每个项目都要定义成百上千个这样的接口!
💡 设计哲学:为什么需要标准化的函数类型?
// 🎯 设计洞察:函数签名的本质分类
// 
// 观察这些Lambda表达式:
name -> name.length()        // String → Integer
text -> text.toUpperCase()   // String → String  
age -> age > 18             // Integer → Boolean
() -> Math.random()         // () → Double
System.out::println         // String → void// 💡 发现:所有函数本质上只有4种模式!
// 1. T → R     (Function)
// 2. T → boolean (Predicate) 
// 3. T → void  (Consumer)
// 4. () → T    (Supplier)
🔬 深层原理:类型擦除与函数式接口的巧妙设计
// 🧠 智慧设计:如何在类型擦除的Java中实现类型安全?
public class TypeSafetyDemo {public static void main(String[] args) {// 🎯 编译器的类型推断魔法Function<String, Integer> lengthCalculator = String::length;// 🔍 编译器知道:// - 输入必须是String// - 输出必须是Integer// - 方法签名必须匹配Integer result = lengthCalculator.apply("Hello"); // ✅ 类型安全// String wrong = lengthCalculator.apply("Hello"); // ❌ 编译错误// Integer error = lengthCalculator.apply(123);    // ❌ 编译错误}
}

🎯 解决的核心问题:

  • 🎨 API设计统一性 - 避免每个库都定义自己的函数接口
  • ⚡ 类型安全性 - 编译时检查,避免运行时类型错误
  • 🚀 性能优化 - 避免装箱拆箱,支持编译器优化
  • 🔗 生态互操作 - 不同库之间可以无缝协作

2.3 怎么做(How)

🎮 实战游戏:函数式接口大师养成记

让我们通过一个有趣的数据处理管道系统来掌握函数式接口的精髓!

🏭 场景:智能数据处理工厂
import java.util.function.*;
import java.util.*;
import java.util.stream.Collectors;public class DataProcessingFactory {// 📊 模拟数据:用户购买记录static class Purchase {String userName;String product;double amount;String category;public Purchase(String userName, String product, double amount, String category) {this.userName = userName; this.product = product; this.amount = amount; this.category = category;}@Overridepublic String toString() {return String.format("%s购买了%s(%.2f元)", userName, product, amount);}// getters...public String getUserName() { return userName; }public String getProduct() { return product; }public double getAmount() { return amount; }public String getCategory() { return category; }}public static void main(String[] args) {// 🔍 1. Predicate - 过滤器Predicate<Purchase> isHighValue = p -> p.getAmount() > 1000;Predicate<Purchase> isDigital = p -> "数码".equals(p.getCategory());Predicate<Purchase> combined = isHighValue.and(isDigital); // 组合// 🔄 2. Function - 转换器Function<Purchase, String> toName = Purchase::getUserName;Function<String, String> addTitle = name -> "尊贵的" + name;Function<Purchase, String> pipeline = toName.andThen(addTitle); // 链式// 🍽️ 3. Consumer - 消费者Consumer<Purchase> emailer = p -> sendEmail(p);Consumer<Purchase> smser = p -> sendSMS(p);Consumer<Purchase> notifier = emailer.andThen(smser); // 组合// 🏭 4. Supplier - 生成器Supplier<String> idGen = () -> UUID.randomUUID().toString();}
}
自定义函数式接口
@FunctionalInterface
interface MathOperation {int operate(int a, int b);
}public class CustomFunctionalInterface {public static void main(String[] args) {MathOperation addition = (a, b) -> a + b;MathOperation multiplication = (a, b) -> a * b;System.out.println("10 + 5 = " + addition.operate(10, 5));System.out.println("10 * 5 = " + multiplication.operate(10, 5));}
}
Java 8前后的对比

对比1:自定义函数式接口

// Java 8之前:需要创建完整的接口实现
interface MathOperation {int operate(int a, int b);
}class MathOperationImpl implements MathOperation {@Overridepublic int operate(int a, int b) {return a + b;}
}public class FunctionalInterfaceComparison {public static void main(String[] args) {// Java 8之前:需要创建实现类MathOperation addition = new MathOperationImpl();System.out.println("旧方式: " + addition.operate(10, 5));// Java 8:直接使用Lambda表达式MathOperation additionLambda = (a, b) -> a + b;System.out.println("Lambda方式: " + additionLambda.operate(10, 5));// 更灵活:可以动态定义操作MathOperation multiplication = (a, b) -> a * b;MathOperation division = (a, b) -> a / b;System.out.println("乘法: " + multiplication.operate(10, 5));System.out.println("除法: " + division.operate(10, 5));}
}

对比2:集合操作

import java.util.*;
import java.util.function.Predicate;public class CollectionOperationComparison {public static void main(String[] args) {List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Eve");// Java 8之前:手动实现过滤System.out.println("=== Java 8之前:手动过滤 ===");List<String> filteredOld = new ArrayList<>();for (String name : names) {if (name.length() > 3) {filteredOld.add(name);}}System.out.println("过滤结果: " + filteredOld);// Java 8:使用Predicate和StreamSystem.out.println("\n=== Java 8:使用Predicate ===");Predicate<String> lengthFilter = name -> name.length() > 3;List<String> filteredNew = names.stream().filter(lengthFilter).collect(Collectors.toList());System.out.println("过滤结果: " + filteredNew);// 更灵活:组合多个条件Predicate<String> startsWithA = name -> name.startsWith("A");Predicate<String> longName = name -> name.length() > 3;List<String> complexFiltered = names.stream().filter(startsWithA.and(longName)).collect(Collectors.toList());System.out.println("复杂过滤结果: " + complexFiltered);}
}

本质改变:

  • 类型安全:编译时类型检查,避免运行时错误
  • 代码复用:标准化的函数接口,提高代码复用性
  • API设计:为Java标准库提供了统一的函数式编程基础

3. Stream API 🌊

🎮 魔法比喻:如果说Collection是一个装满宝藏的箱子,那么Stream就是一条魔法传送带!

你可以在传送带上设置各种魔法阵(filter、map、sort),宝藏经过时会自动变化,最终到达你想要的形态。

3.1 是什么(What)

🌊 Stream的魔法世界

Stream API不是"流",它是一个数据处理的魔法工坊!想象一下工业流水线:

// 🏭 数据流水线:原材料 → 加工过程 → 最终产品
List<String> names = Arrays.asList("alice", "BOB", "charlie", "DIANA");// 🎯 传统方式:手工作坊(命令式)
List<String> result1 = new ArrayList<>();
for (String name : names) {if (name.length() > 3) {                    // 👨‍🔧 工人1:筛选长度String capitalized = name.toUpperCase(); // 👨‍🔧 工人2:转大写result1.add(capitalized);               // 👨‍🔧 工人3:收集结果}
}// 🚀 Stream方式:智能流水线(声明式)
List<String> result2 = names.stream().filter(name -> name.length() > 3)    // 🤖 机器人1:自动筛选.map(String::toUpperCase)             // 🤖 机器人2:自动转换.collect(Collectors.toList());        // 🤖 机器人3:自动收集
🧠 深度解析:Stream的三重境界
// 🎯 境界一:数据源(Source)
Stream<String> sourceStream = Arrays.asList("A", "B", "C").stream();
Stream<Integer> rangeStream = IntStream.range(1, 100).boxed();
Stream<String> fileStream = Files.lines(Paths.get("data.txt"));// ⚡ 境界二:中间操作(Intermediate Operations)
// 特点:懒惰执行,返回新的Stream,可以链式调用
sourceStream.filter(s -> s.length() > 1)     // 🔍 过滤器:筛选符合条件的元素.map(String::toLowerCase)        // 🔄 映射器:转换每个元素.sorted()                        // 🏆 排序器:重新排列元素.distinct()                      // 🎯 去重器:移除重复元素.limit(10);                      // ✂️ 限制器:只取前N个// 🎬 境界三:终端操作(Terminal Operations)  
// 特点:立即执行,触发整个流水线运行,产生最终结果
sourceStream.collect(Collectors.toList())    // 📦 收集成List.forEach(System.out::println)    // 🖨️ 逐个处理.reduce(String::concat)          // 🔄 聚合操作.count();                        // 🔢 计数统计
🔬 惰性求值的秘密
public class LazyEvaluationDemo {public static void main(String[] args) {List<String> words = Arrays.asList("apple", "banana", "cherry", "date");System.out.println("🎬 开始创建Stream...");Stream<String> stream = words.stream().filter(word -> {System.out.println("🔍 过滤: " + word);return word.length() > 4;}).map(word -> {System.out.println("🔄 转换: " + word);return word.toUpperCase();});System.out.println("💡 Stream创建完成,但还没有任何输出!");System.out.println("🚀 现在开始终端操作...");// 只有调用终端操作,整个流水线才开始工作!List<String> result = stream.collect(Collectors.toList());System.out.println("📦 最终结果: " + result);}
}

3.2 为什么(Why)

📚 历史的呼唤:集合操作的进化史
// 😱 史前时代:Java 1.0的噩梦
Vector<String> names = new Vector<>();
names.addElement("Alice");
names.addElement("Bob");
names.addElement("Charlie");Vector<String> filtered = new Vector<>();
for (int i = 0; i < names.size(); i++) {String name = names.elementAt(i);if (name.length() > 3) {filtered.addElement(name.toUpperCase());}
}// 😐 进步时代:Java 1.5的改善
List<String> names2 = Arrays.asList("Alice", "Bob", "Charlie");
List<String> filtered2 = new ArrayList<>();
for (String name : names2) {if (name.length() > 3) {filtered2.add(name.toUpperCase());}
}// 🎉 现代时代:Java 8的革命
List<String> filtered3 = names2.stream().filter(name -> name.length() > 3).map(String::toUpperCase).collect(Collectors.toList());
💡 设计哲学:为什么需要声明式编程?
// 🧠 思维方式的根本转变// 命令式思维:How(怎么做)
// "计算机,你要这样做:先遍历,然后检查每个元素,如果符合条件就..."
List<String> result = new ArrayList<>();
for (String item : list) {if (condition(item)) {result.add(transform(item));}
}// 声明式思维:What(做什么)  
// "计算机,我要所有符合条件的元素经过转换后的结果"
List<String> result = list.stream().filter(this::condition).map(this::transform).collect(toList());
⚡ 性能革命:并行计算的民主化
// 🐌 传统并行编程:专家级难度
public class TraditionalParallel {private static final int THREAD_COUNT = Runtime.getRuntime().availableProcessors();public static List<Integer> parallelSquare(List<Integer> numbers) {ExecutorService executor = Executors.newFixedThreadPool(THREAD_COUNT);List<Future<List<Integer>>> futures = new ArrayList<>();int chunkSize = numbers.size() / THREAD_COUNT;for (int i = 0; i < THREAD_COUNT; i++) {final int start = i * chunkSize;final int end = (i == THREAD_COUNT - 1) ? numbers.size() : (i + 1) * chunkSize;futures.add(executor.submit(() -> {List<Integer> chunk = new ArrayList<>();for (int j = start; j < end; j++) {chunk.add(numbers.get(j) * numbers.get(j));}return chunk;}));}List<Integer> result = new ArrayList<>();for (Future<List<Integer>> future : futures) {try {result.addAll(future.get());} catch (Exception e) {throw new RuntimeException(e);}}executor.shutdown();return result;}
}// 🚀 Stream并行:一行代码的魔法
List<Integer> result = numbers.parallelStream().map(n -> n * n).collect(toList());
🎯 解决的核心痛点
  • 🎨 表达力危机 - 让代码更接近自然语言描述
  • 🔧 复杂性管理 - 将数据操作从业务逻辑中分离
  • ⚡ 并发编程门槛 - 让普通开发者也能轻松使用并行计算
  • 🐛 错误减少 - 减少手动循环中的off-by-one等错误
  • 🎪 组合能力 - 支持操作的链式组合和复用

3.3 怎么做(How)

Stream操作分类
import java.util.*;
import java.util.stream.*;public class StreamAPIExample {public static void main(String[] args) {List<Person> people = Arrays.asList(new Person("Alice", 25, "Engineer"),new Person("Bob", 30, "Manager"),new Person("Charlie", 35, "Engineer"),new Person("David", 28, "Designer"),new Person("Eve", 32, "Engineer"));// 1. 中间操作:filter, map, sorted等System.out.println("=== 工程师年龄大于30 ===");people.stream().filter(p -> "Engineer".equals(p.getJob())).filter(p -> p.getAge() > 30).map(Person::getName).forEach(System.out::println);// 2. 终端操作:collect, forEach, reduce等System.out.println("\n=== 按年龄分组 ===");Map<String, List<Person>> groupedByJob = people.stream().collect(Collectors.groupingBy(Person::getJob));groupedByJob.forEach((job, personList) -> {System.out.println(job + ": " + personList.size() + "人");});// 3. 并行流处理System.out.println("\n=== 并行计算平均年龄 ===");double avgAge = people.parallelStream().mapToInt(Person::getAge).average().orElse(0.0);System.out.println("平均年龄: " + avgAge);// 4. 复杂数据处理 - 性能对比演示System.out.println("\n=== 性能对比:串行 vs 并行 ===");performanceComparison();}// ⚡ 性能对比演示private static void performanceComparison() {// 创建大数据集List<Integer> bigList = IntStream.rangeClosed(1, 10_000_000).boxed().collect(Collectors.toList());System.out.println("数据集大小: " + bigList.size());// 串行处理long startTime = System.currentTimeMillis();long serialSum = bigList.stream().filter(n -> n % 2 == 0).mapToLong(n -> n * n).sum();long serialTime = System.currentTimeMillis() - startTime;// 并行处理startTime = System.currentTimeMillis();long parallelSum = bigList.parallelStream().filter(n -> n % 2 == 0).mapToLong(n -> n * n).sum();long parallelTime = System.currentTimeMillis() - startTime;System.out.printf("串行处理: 结果=%d, 耗时=%dms%n", serialSum, serialTime);System.out.printf("并行处理: 结果=%d, 耗时=%dms%n", parallelSum, parallelTime);System.out.printf("性能提升: %.2fx%n", (double) serialTime / parallelTime);}
}
🧙‍♂️ 高级技巧:Stream API的魔法秘籍

🧠 核心技巧总结

  1. flatMap扁平化
// 处理嵌套结构
List<String> flat = nestedList.stream().flatMap(List::stream).collect(toList());
  1. 无限Stream
// 斐波那契数列
Stream.iterate(new int[]{0, 1}, arr -> new int[]{arr[1], arr[0] + arr[1]}).limit(10);
  1. 短路操作
// 找到就停止
Optional<Integer> first = numbers.stream().filter(condition).findFirst();

class Person {
private String name;
private int age;
private String job;

public Person(String name, int age, String job) {this.name = name;this.age = age;this.job = job;
}// getters
public String getName() { return name; }
public int getAge() { return age; }
public String getJob() { return job; }

}


#### Stream操作详解**中间操作(Intermediate Operations)**
```java
public class StreamOperations {public static void main(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);// filter - 过滤System.out.println("偶数: " + numbers.stream().filter(n -> n % 2 == 0).collect(Collectors.toList()));// map - 转换System.out.println("平方数: " + numbers.stream().map(n -> n * n).collect(Collectors.toList()));// flatMap - 扁平化List<List<Integer>> nestedLists = Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3, 4), Arrays.asList(5, 6));System.out.println("扁平化: " + nestedLists.stream().flatMap(List::stream).collect(Collectors.toList()));// sorted - 排序System.out.println("降序: " + numbers.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList()));// distinct - 去重List<Integer> duplicates = Arrays.asList(1, 2, 2, 3, 3, 3, 4);System.out.println("去重: " + duplicates.stream().distinct().collect(Collectors.toList()));}
}

终端操作(Terminal Operations)

public class TerminalOperations {public static void main(String[] args) {List<String> words = Arrays.asList("hello", "world", "java", "stream", "api");// forEach - 遍历System.out.println("遍历输出:");words.stream().forEach(System.out::println);// collect - 收集List<String> upperCaseWords = words.stream().map(String::toUpperCase).collect(Collectors.toList());System.out.println("大写: " + upperCaseWords);// reduce - 归约String concatenated = words.stream().reduce("", (a, b) -> a + " " + b);System.out.println("连接: " + concatenated);// anyMatch, allMatch, noneMatch - 匹配boolean hasLongWord = words.stream().anyMatch(s -> s.length() > 4);boolean allShort = words.stream().allMatch(s -> s.length() <= 5);boolean noEmpty = words.stream().noneMatch(String::isEmpty);System.out.println("有长单词: " + hasLongWord);System.out.println("都短: " + allShort);System.out.println("无空字符串: " + noEmpty);// findFirst, findAny - 查找Optional<String> first = words.stream().findFirst();Optional<String> any = words.stream().findAny();System.out.println("第一个: " + first.orElse("无"));System.out.println("任意一个: " + any.orElse("无"));}
}
Java 8前后的对比

对比1:集合过滤和转换

import java.util.*;
import java.util.stream.Collectors;public class StreamComparisonExample {public static void main(String[] args) {List<Person> people = Arrays.asList(new Person("Alice", 25, "Engineer"),new Person("Bob", 30, "Manager"),new Person("Charlie", 35, "Engineer"),new Person("David", 28, "Designer"),new Person("Eve", 32, "Engineer"));// Java 8之前:手动实现过滤和转换System.out.println("=== Java 8之前:手动实现 ===");List<String> engineerNamesOld = new ArrayList<>();for (Person person : people) {if ("Engineer".equals(person.getJob())) {if (person.getAge() > 30) {engineerNamesOld.add(person.getName().toUpperCase());}}}System.out.println("工程师名字(大写): " + engineerNamesOld);// Java 8:使用Stream APISystem.out.println("\n=== Java 8:Stream API ===");List<String> engineerNamesNew = people.stream().filter(p -> "Engineer".equals(p.getJob())).filter(p -> p.getAge() > 30).map(Person::getName).map(String::toUpperCase).collect(Collectors.toList());System.out.println("工程师名字(大写): " + engineerNamesNew);}
}
对比2:数据分组统计
public class GroupingComparisonExample {public static void main(String[] args) {List<Person> people = Arrays.asList(new Person("Alice", 25, "Engineer"),new Person("Bob", 30, "Manager"),new Person("Charlie", 35, "Engineer"),new Person("David", 28, "Designer"),new Person("Eve", 32, "Engineer"));// Java 8之前:手动实现分组System.out.println("=== Java 8之前:手动分组 ===");Map<String, List<Person>> groupedByJobOld = new HashMap<>();for (Person person : people) {String job = person.getJob();if (!groupedByJobOld.containsKey(job)) {groupedByJobOld.put(job, new ArrayList<>());}groupedByJobOld.get(job).add(person);}// 计算每个职业的人数Map<String, Integer> jobCountOld = new HashMap<>();for (Map.Entry<String, List<Person>> entry : groupedByJobOld.entrySet()) {jobCountOld.put(entry.getKey(), entry.getValue().size());}System.out.println("职业统计: " + jobCountOld);// Java 8:使用Stream APISystem.out.println("\n=== Java 8:Stream API ===");Map<String, Long> jobCountNew = people.stream().collect(Collectors.groupingBy(Person::getJob,Collectors.counting()));System.out.println("职业统计: " + jobCountNew);// 更复杂的统计:按职业分组,计算平均年龄Map<String, Double> avgAgeByJob = people.stream().collect(Collectors.groupingBy(Person::getJob,Collectors.averagingInt(Person::getAge)));System.out.println("职业平均年龄: " + avgAgeByJob);}
}
对比3:并行处理
public class ParallelProcessingComparison {public static void main(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);// Java 8之前:手动实现并行处理System.out.println("=== Java 8之前:手动并行 ===");long startTime = System.currentTimeMillis();// 创建多个线程处理int threadCount = 4;int chunkSize = numbers.size() / threadCount;List<Thread> threads = new ArrayList<>();List<Integer> results = Collections.synchronizedList(new ArrayList<>());for (int i = 0; i < threadCount; i++) {final int start = i * chunkSize;final int end = (i == threadCount - 1) ? numbers.size() : (i + 1) * chunkSize;Thread thread = new Thread(() -> {for (int j = start; j < end; j++) {int num = numbers.get(j);// 模拟复杂计算try { Thread.sleep(100); } catch (InterruptedException e) {}results.add(num * num);}});threads.add(thread);thread.start();}// 等待所有线程完成for (Thread thread : threads) {try { thread.join(); } catch (InterruptedException e) {}}long endTime = System.currentTimeMillis();System.out.println("手动并行处理时间: " + (endTime - startTime) + "ms");System.out.println("结果数量: " + results.size());// Java 8:使用并行流System.out.println("\n=== Java 8:并行流 ===");startTime = System.currentTimeMillis();List<Integer> parallelResults = numbers.parallelStream().map(num -> {try { Thread.sleep(100); } catch (InterruptedException e) {}return num * num;}).collect(Collectors.toList());endTime = System.currentTimeMillis();System.out.println("并行流处理时间: " + (endTime - startTime) + "ms");System.out.println("结果数量: " + parallelResults.size());}
}

4. Optional类

4.1 是什么(What)

Optional是Java 8引入的一个容器类,用于包装可能为null的对象。它提供了一种优雅的方式来处理null值,避免NullPointerException。

核心概念:

  • 容器类:包装可能为null的对象
  • 类型安全:泛型支持,编译时类型检查
  • 函数式风格:支持链式调用和函数组合
  • 空值语义:明确表达"可能为空"的语义

4.2 为什么(Why)

解决的问题:

  • 空指针异常:减少NullPointerException的发生
  • 代码可读性:明确表达"可能为空"的语义
  • 函数式编程:支持链式调用和函数组合
  • API设计:强制开发者考虑空值情况
  • 代码健壮性:提高程序的稳定性和可靠性

4.3 怎么做(How)

基本用法
import java.util.Optional;public class OptionalExample {public static void main(String[] args) {// 创建Optional对象Optional<String> empty = Optional.empty();Optional<String> of = Optional.of("Hello");Optional<String> ofNullable = Optional.ofNullable(null);// 判断是否为空System.out.println("empty.isPresent(): " + empty.isPresent());System.out.println("of.isPresent(): " + of.isPresent());System.out.println("ofNullable.isPresent(): " + ofNullable.isPresent());// 获取值(不安全)try {String value = empty.get(); // 抛出NoSuchElementException} catch (Exception e) {System.out.println("获取空值异常: " + e.getMessage());}// 安全获取值String safeValue = of.orElse("默认值");String safeValue2 = ofNullable.orElseGet(() -> "计算得到的默认值");String safeValue3 = ofNullable.orElseThrow(() -> new RuntimeException("值不存在"));System.out.println("安全获取: " + safeValue);System.out.println("安全获取2: " + safeValue2);}
}
高级用法
public class OptionalAdvancedExample {public static void main(String[] args) {// 链式操作Optional<String> result = Optional.of("hello world").filter(s -> s.length() > 5).map(String::toUpperCase).map(s -> s + "!");System.out.println("链式操作结果: " + result.orElse("无结果"));// 条件执行Optional<String> name = Optional.of("Alice");name.ifPresent(n -> System.out.println("Hello, " + n));// 组合多个OptionalOptional<String> firstName = Optional.of("John");Optional<String> lastName = Optional.of("Doe");String fullName = firstName.flatMap(f -> lastName.map(l -> f + " " + l)).orElse("Unknown");System.out.println("全名: " + fullName);// 实际应用场景User user = new User("bob@example.com");String displayName = Optional.of(user).map(User::getEmail).map(email -> email.substring(0, email.indexOf('@'))).map(String::toUpperCase).orElse("Unknown User");System.out.println("显示名称: " + displayName);}
}class User {private String email;public User(String email) {this.email = email;}public String getEmail() {return email;}
}
最佳实践
public class OptionalBestPractices {public static void main(String[] args) {// 不要这样使用OptionalOptional<String> bad = Optional.of("value");if (bad.isPresent()) {String value = bad.get(); // 反模式System.out.println(value);}// 应该这样使用Optional<String> good = Optional.of("value");good.ifPresent(System.out::println);// 避免Optional.of(null)try {Optional<String> bad2 = Optional.of(null); // 抛出异常} catch (Exception e) {System.out.println("不能使用Optional.of(null): " + e.getMessage());}// 使用Optional.ofNullableOptional<String> good2 = Optional.ofNullable(null); // 安全System.out.println("ofNullable(null) isPresent: " + good2.isPresent());}
}
Java 8前后的对比

对比1:空值处理

public class NullHandlingComparison {public static void main(String[] args) {// Java 8之前:手动空值检查System.out.println("=== Java 8之前:手动空值检查 ===");String name = getUserName(); // 可能返回nullString displayName;if (name != null) {if (name.length() > 0) {displayName = name.toUpperCase();} else {displayName = "Unknown";}} else {displayName = "Unknown";}System.out.println("显示名称: " + displayName);// Java 8:使用OptionalSystem.out.println("\n=== Java 8:使用Optional ===");String displayNameNew = Optional.ofNullable(getUserName()).filter(n -> n.length() > 0).map(String::toUpperCase).orElse("Unknown");System.out.println("显示名称: " + displayNameNew);}private static String getUserName() {// 模拟可能返回null的方法return Math.random() > 0.5 ? "Alice" : null;}
}

对比2:方法链式调用

public class MethodChainingComparison {public static void main(String[] args) {User user = getUser(); // 可能返回null// Java 8之前:嵌套空值检查System.out.println("=== Java 8之前:嵌套检查 ===");String email = null;if (user != null) {Profile profile = user.getProfile();if (profile != null) {ContactInfo contactInfo = profile.getContactInfo();if (contactInfo != null) {email = contactInfo.getEmail();}}}String displayEmail = email != null ? email : "No email";System.out.println("邮箱: " + displayEmail);// Java 8:使用Optional链式调用System.out.println("\n=== Java 8:Optional链式调用 ===");String displayEmailNew = Optional.ofNullable(user).map(User::getProfile).map(Profile::getContactInfo).map(ContactInfo::getEmail).orElse("No email");System.out.println("邮箱: " + displayEmailNew);}private static User getUser() {// 模拟可能返回null的方法return Math.random() > 0.5 ? new User() : null;}
}// 模拟类
class User {public Profile getProfile() {return Math.random() > 0.5 ? new Profile() : null;}
}class Profile {public ContactInfo getContactInfo() {return Math.random() > 0.5 ? new ContactInfo() : null;}
}class ContactInfo {public String getEmail() {return "user@example.com";}
}
对比3:集合中的空值处理
import java.util.*;public class CollectionNullHandlingComparison {public static void main(String[] args) {List<String> names = Arrays.asList("Alice", null, "Bob", null, "Charlie");// Java 8之前:手动过滤null值System.out.println("=== Java 8之前:手动过滤null ===");List<String> validNamesOld = new ArrayList<>();for (String name : names) {if (name != null && name.length() > 0) {validNamesOld.add(name.toUpperCase());}}System.out.println("有效名字: " + validNamesOld);// Java 8:使用Optional和StreamSystem.out.println("\n=== Java 8:Optional + Stream ===");List<String> validNamesNew = names.stream().map(Optional::ofNullable).filter(Optional::isPresent).map(Optional::get).filter(name -> name.length() > 0).map(String::toUpperCase).collect(Collectors.toList());System.out.println("有效名字: " + validNamesNew);// 更简洁的写法List<String> validNamesSimple = names.stream().filter(Objects::nonNull).filter(name -> name.length() > 0).map(String::toUpperCase).collect(Collectors.toList());System.out.println("简化写法: " + validNamesSimple);}
}

5. 新的日期时间API

5.1 是什么(What)

Java 8引入了全新的日期时间API(java.time包),提供了不可变、线程安全的日期时间处理类。

核心类:

  • LocalDate:表示日期(年-月-日)
  • LocalTime:表示时间(时:分:秒)
  • LocalDateTime:表示日期时间
  • ZonedDateTime:表示带时区的日期时间
  • DateTimeFormatter:日期时间格式化

5.2 为什么(Why)

解决的问题:

  • 可变性:Date和Calendar是可变的,线程不安全
  • 设计缺陷:月份从0开始,年份从1900开始
  • 时区处理复杂:缺乏统一的时区处理机制
  • 格式化困难:SimpleDateFormat线程不安全
  • API一致性:提供统一的日期时间处理方式

5.3 怎么做(How)

核心类介绍
import java.time.*;
import java.time.format.*;
import java.time.temporal.*;public class NewDateTimeAPIExample {public static void main(String[] args) {// LocalDate - 日期LocalDate today = LocalDate.now();LocalDate specificDate = LocalDate.of(2024, 1, 15);LocalDate parsedDate = LocalDate.parse("2024-01-15");System.out.println("今天: " + today);System.out.println("特定日期: " + specificDate);System.out.println("解析日期: " + parsedDate);// LocalTime - 时间LocalTime now = LocalTime.now();LocalTime specificTime = LocalTime.of(14, 30, 45);LocalTime parsedTime = LocalTime.parse("14:30:45");System.out.println("现在时间: " + now);System.out.println("特定时间: " + specificTime);System.out.println("解析时间: " + parsedTime);// LocalDateTime - 日期时间LocalDateTime dateTime = LocalDateTime.now();LocalDateTime combined = LocalDateTime.of(specificDate, specificTime);System.out.println("当前日期时间: " + dateTime);System.out.println("组合日期时间: " + combined);// ZonedDateTime - 带时区的日期时间ZonedDateTime zonedDateTime = ZonedDateTime.now();ZoneId tokyoZone = ZoneId.of("Asia/Tokyo");ZonedDateTime tokyoTime = ZonedDateTime.now(tokyoZone);System.out.println("本地时区: " + zonedDateTime);System.out.println("东京时间: " + tokyoTime);}
}
日期时间操作
public class DateTimeOperations {public static void main(String[] args) {LocalDate today = LocalDate.now();// 日期计算LocalDate tomorrow = today.plusDays(1);LocalDate nextWeek = today.plusWeeks(1);LocalDate nextMonth = today.plusMonths(1);LocalDate nextYear = today.plusYears(1);System.out.println("明天: " + tomorrow);System.out.println("下周: " + nextWeek);System.out.println("下月: " + nextMonth);System.out.println("明年: " + nextYear);// 日期比较LocalDate future = LocalDate.of(2025, 12, 31);boolean isFuture = future.isAfter(today);boolean isPast = today.isBefore(future);boolean isEqual = today.equals(today);System.out.println("是未来: " + isFuture);System.out.println("是过去: " + isPast);System.out.println("是今天: " + isEqual);// 日期信息获取DayOfWeek dayOfWeek = today.getDayOfWeek();int dayOfMonth = today.getDayOfMonth();int dayOfYear = today.getDayOfYear();Month month = today.getMonth();int year = today.getYear();System.out.println("星期: " + dayOfWeek);System.out.println("月中第几天: " + dayOfMonth);System.out.println("年中第几天: " + dayOfYear);System.out.println("月份: " + month);System.out.println("年份: " + year);}
}
格式化与解析
public class DateTimeFormatting {public static void main(String[] args) {LocalDateTime now = LocalDateTime.now();// 预定义格式DateTimeFormatter formatter1 = DateTimeFormatter.ISO_LOCAL_DATE_TIME;String formatted1 = now.format(formatter1);System.out.println("ISO格式: " + formatted1);// 自定义格式DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");String formatted2 = now.format(formatter2);System.out.println("中文格式: " + formatted2);// 解析字符串String dateStr = "2024-01-15 14:30:00";DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");LocalDateTime parsed = LocalDateTime.parse(dateStr, formatter3);System.out.println("解析结果: " + parsed);// 本地化格式DateTimeFormatter formatter4 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withLocale(java.util.Locale.CHINA);String localized = now.format(formatter4);System.out.println("本地化格式: " + localized);}
}
时区处理
public class TimeZoneHandling {public static void main(String[] args) {// 获取所有可用时区Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();System.out.println("可用时区数量: " + availableZoneIds.size());// 时区转换LocalDateTime localDateTime = LocalDateTime.now();ZoneId localZone = ZoneId.systemDefault();ZoneId utcZone = ZoneId.of("UTC");ZoneId tokyoZone = ZoneId.of("Asia/Tokyo");ZonedDateTime localZoned = localDateTime.atZone(localZone);ZonedDateTime utcZoned = localZoned.withZoneSameInstant(utcZone);ZonedDateTime tokyoZoned = localZoned.withZoneSameInstant(tokyoZone);System.out.println("本地时间: " + localZoned);System.out.println("UTC时间: " + utcZoned);System.out.println("东京时间: " + tokyoZoned);// 时区偏移ZoneOffset offset = ZoneOffset.ofHours(8);OffsetDateTime offsetDateTime = localDateTime.atOffset(offset);System.out.println("偏移时间: " + offsetDateTime);}
}
Java 8前后的对比

对比1:日期创建和操作

import java.util.*;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;public class DateCreationComparison {public static void main(String[] args) {// Java 8之前:使用Date和CalendarSystem.out.println("=== Java 8之前:Date和Calendar ===");// 创建当前时间Date now = new Date();System.out.println("当前时间: " + now);// 创建特定日期(注意:月份从0开始)Calendar calendar = Calendar.getInstance();calendar.set(2024, Calendar.JANUARY, 15, 14, 30, 0); // 月份从0开始!Date specificDate = calendar.getTime();System.out.println("特定日期: " + specificDate);// 日期计算(加一天)calendar.add(Calendar.DAY_OF_MONTH, 1);Date tomorrow = calendar.getTime();System.out.println("明天: " + tomorrow);// 格式化日期SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");String formatted = sdf.format(tomorrow);System.out.println("格式化后: " + formatted);// Java 8:新的日期时间APISystem.out.println("\n=== Java 8:新的日期时间API ===");// 创建当前时间LocalDateTime nowNew = LocalDateTime.now();System.out.println("当前时间: " + nowNew);// 创建特定日期(月份从1开始,更直观)LocalDateTime specificDateNew = LocalDateTime.of(2024, 1, 15, 14, 30, 0);System.out.println("特定日期: " + specificDateNew);// 日期计算(加一天)LocalDateTime tomorrowNew = specificDateNew.plusDays(1);System.out.println("明天: " + tomorrowNew);// 格式化日期DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");String formattedNew = tomorrowNew.format(formatter);System.out.println("格式化后: " + formattedNew);}
}

对比2:时区处理

public class TimeZoneComparison {public static void main(String[] args) {// Java 8之前:时区处理复杂System.out.println("=== Java 8之前:复杂时区处理 ===");Calendar calendar = Calendar.getInstance();TimeZone localZone = TimeZone.getDefault();TimeZone tokyoZone = TimeZone.getTimeZone("Asia/Tokyo");// 设置时区calendar.setTimeZone(tokyoZone);Date tokyoTime = calendar.getTime();// 转换时区calendar.setTimeZone(localZone);Date localTime = calendar.getTime();System.out.println("东京时间: " + tokyoTime);System.out.println("本地时间: " + localTime);// 获取时区偏移int offset = tokyoZone.getOffset(System.currentTimeMillis());int hours = offset / (1000 * 60 * 60);System.out.println("东京时区偏移: " + hours + "小时");// Java 8:简洁的时区处理System.out.println("\n=== Java 8:简洁时区处理 ===");LocalDateTime localDateTime = LocalDateTime.now();ZoneId localZoneId = ZoneId.systemDefault();ZoneId tokyoZoneId = ZoneId.of("Asia/Tokyo");ZonedDateTime localZoned = localDateTime.atZone(localZoneId);ZonedDateTime tokyoZoned = localDateTime.atZone(tokyoZoneId);System.out.println("本地时区时间: " + localZoned);System.out.println("东京时区时间: " + tokyoZoned);// 时区转换ZonedDateTime converted = localZoned.withZoneSameInstant(tokyoZoneId);System.out.println("转换到东京时区: " + converted);// 获取时区偏移ZoneOffset offsetNew = tokyoZoned.getOffset();System.out.println("东京时区偏移: " + offsetNew.getTotalSeconds() / 3600 + "小时");}
}

对比3:日期解析和验证

public class DateParsingComparison {public static void main(String[] args) {String dateStr = "2024-01-15";// Java 8之前:使用SimpleDateFormat(线程不安全)System.out.println("=== Java 8之前:SimpleDateFormat ===");try {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");Date parsedDate = sdf.parse(dateStr);System.out.println("解析结果: " + parsedDate);// 验证日期(需要额外检查)Calendar cal = Calendar.getInstance();cal.setTime(parsedDate);cal.setLenient(false); // 严格模式cal.getTime(); // 会抛出异常如果日期无效} catch (Exception e) {System.out.println("解析异常: " + e.getMessage());}// Java 8:使用DateTimeFormatter(线程安全)System.out.println("\n=== Java 8:DateTimeFormatter ===");try {DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");LocalDate parsedDateNew = LocalDate.parse(dateStr, formatter);System.out.println("解析结果: " + parsedDateNew);// 验证日期(自动验证)LocalDate validDate = LocalDate.of(2024, 1, 15);System.out.println("有效日期: " + validDate);// 无效日期会抛出异常try {LocalDate invalidDate = LocalDate.of(2024, 2, 30); // 2月没有30号System.out.println("无效日期: " + invalidDate);} catch (Exception e) {System.out.println("无效日期异常: " + e.getMessage());}} catch (Exception e) {System.out.println("解析异常: " + e.getMessage());}}
}
// Java 8:接口默认方法
interface EnhancedCollection<T> extends Collection<T> {default void forEach(Consumer<? super T> action) {for (T item : this) {action.accept(item);}}default boolean removeIf(Predicate<? super T> filter) {boolean removed = false;Iterator<T> iterator = iterator();while (iterator.hasNext()) {if (filter.test(iterator.next())) {iterator.remove();removed = true;}}return removed;}
}public class InterfaceEvolutionComparison {public static void main(String[] args) {List<String> names = Arrays.asList("Alice", "Bob", "Charlie");// Java 8之前:使用工具类System.out.println("=== Java 8之前:工具类 ===");CollectionUtils.forEach(names, name -> System.out.println("Hello, " + name));// Java 8:直接使用接口默认方法System.out.println("\n=== Java 8:接口默认方法 ===");names.forEach(name -> System.out.println("Hello, " + name));// 更自然的使用方式List<String> mutableNames = new ArrayList<>(names);mutableNames.removeIf(name -> name.startsWith("A"));System.out.println("移除A开头的名字: " + mutableNames);}
}
对比3:多重继承支持
// Java 8之前:无法实现多重继承
interface Flyable {void fly();
}interface Swimmable {void swim();
}// 必须选择实现其中一个,或者创建组合类
class Bird implements Flyable {@Overridepublic void fly() {System.out.println("鸟儿飞翔");}
}class Fish implements Swimmable {@Overridepublic void swim() {System.out.println("鱼儿游泳");}
}// Java 8:通过默认方法实现有限的多重继承
interface FlyableNew {default void fly() {System.out.println("飞翔");}
}interface SwimmableNew {default void swim() {System.out.println("游泳");}
}// 一个类可以实现多个接口,获得默认行为
class Duck implements FlyableNew, SwimmableNew {// 不需要实现任何方法,直接获得默认行为// 也可以重写默认方法@Overridepublic void fly() {System.out.println("鸭子飞翔");}
}public class MultipleInheritanceComparison {public static void main(String[] args) {// Java 8之前:需要分别创建对象Bird bird = new Bird();Fish fish = new Fish();bird.fly();fish.swim();// Java 8:一个对象具有多种能力System.out.println("\n=== Java 8:多重继承 ===");Duck duck = new Duck();duck.fly();duck.swim();}
}

6. 接口默认方法

6.1 是什么(What)

接口默认方法是Java 8引入的特性,允许在接口中定义具有默认实现的方法。这使得接口可以包含具体的方法实现,而不仅仅是抽象方法声明。

核心概念:

  • 默认实现:接口可以包含具体方法实现
  • 向后兼容:可以在不破坏现有实现的情况下添加新方法
  • 多重继承:提供有限的多重继承机制
  • 接口演化:支持接口的渐进式改进

6.2 为什么(Why)

解决的问题:

  • 接口演化:可以在不破坏现有实现的情况下向接口添加新方法
  • 向后兼容性:新方法有默认实现,现有代码无需修改
  • 多重继承:提供了一种有限的多重继承机制
  • API设计:可以定义通用的默认行为
  • 代码复用:避免重复实现相同的功能

6.3 怎么做(How)

基本语法
public interface DefaultMethodExample {// 抽象方法void abstractMethod();// 默认方法default void defaultMethod() {System.out.println("这是默认方法实现");}// 静态方法static void staticMethod() {System.out.println("这是静态方法");}
}class Implementation implements DefaultMethodExample {@Overridepublic void abstractMethod() {System.out.println("实现抽象方法");}// 可以选择重写默认方法,也可以使用默认实现@Overridepublic void defaultMethod() {System.out.println("重写默认方法");}
}
实际应用示例
import java.util.*;public class DefaultMethodPracticalExample {public static void main(String[] args) {List<String> names = Arrays.asList("Alice", "Bob", "Charlie");// 使用List接口的默认方法names.forEach(System.out::println);// 使用Collection接口的默认方法names.removeIf(name -> name.startsWith("A"));System.out.println("移除A开头的名字后: " + names);// 使用Iterable接口的默认方法names.spliterator().forEachRemaining(System.out::println);}
}// 自定义接口示例
interface Logger {void log(String message);default void logError(String message) {log("ERROR: " + message);}default void logInfo(String message) {log("INFO: " + message);}default void logWarning(String message) {log("WARNING: " + message);}
}class ConsoleLogger implements Logger {@Overridepublic void log(String message) {System.out.println(message);}
}class FileLogger implements Logger {@Overridepublic void log(String message) {// 写入文件的实现System.out.println("写入文件: " + message);}// 可以选择重写默认方法@Overridepublic void logError(String message) {log("严重错误: " + message);}
}
多重继承冲突解决
interface A {default void method() {System.out.println("A的默认方法");}
}interface B {default void method() {System.out.println("B的默认方法");}
}// 必须明确指定使用哪个接口的默认方法
class C implements A, B {@Overridepublic void method() {// 调用A的默认方法A.super.method();// 或者调用B的默认方法// B.super.method();// 或者提供自己的实现System.out.println("C的实现");}
}
Java 8前后的对比

对比1:接口演化

// Java 8之前:接口无法添加新方法
interface OldLogger {void log(String message);// 如果要添加新方法,会破坏所有现有实现// void logError(String message); // 这会导致编译错误
}class OldLoggerImpl implements OldLogger {@Overridepublic void log(String message) {System.out.println(message);}// 必须实现所有接口方法
}// Java 8:接口可以添加默认方法
interface NewLogger {void log(String message);// 可以添加新方法而不破坏现有实现default void logError(String message) {log("ERROR: " + message);}default void logInfo(String message) {log("INFO: " + message);}
}class NewLoggerImpl implements NewLogger {@Overridepublic void log(String message) {System.out.println(message);}// 不需要实现默认方法,可以直接使用
}

对比2:工具方法集成

import java.util.*;// Java 8之前:工具类模式
class CollectionUtils {public static <T> void forEach(Collection<T> collection, Consumer<T> action) {for (T item : collection) {action.accept(item);}}public static <T> boolean removeIf(Collection<T> collection, Predicate<T> filter) {boolean removed = false;Iterator<T> iterator = collection.iterator();while (iterator.hasNext()) {if (filter.test(iterator.next())) {iterator.remove();removed = true;}}return removed;}
}// Java 8:接口默认方法
interface EnhancedCollection<T> extends Collection<T> {default void forEach(Consumer<? super T> action) {for (T item : this) {action.accept(item);}}default boolean removeIf(Predicate<? super T> filter) {boolean removed = false;Iterator<T> iterator = iterator();while (iterator.hasNext()) {if (filter.test(iterator.next())) {iterator.remove();removed = true;}}return removed;}
}public class InterfaceEvolutionComparison {public static void main(String[] args) {List<String> names = Arrays.asList("Alice", "Bob", "Charlie");// Java 8之前:使用工具类System.out.println("=== Java 8之前:工具类 ===");CollectionUtils.forEach(names, name -> System.out.println("Hello, " + name));// Java 8:直接使用接口默认方法System.out.println("\n=== Java 8:接口默认方法 ===");names.forEach(name -> System.out.println("Hello, " + name));// 更自然的使用方式List<String> mutableNames = new ArrayList<>(names);mutableNames.removeIf(name -> name.startsWith("A"));System.out.println("移除A开头的名字: " + mutableNames);}
}

本质改变:

  • 接口演化:可以在不破坏现有实现的情况下向接口添加新方法
  • 向后兼容性:新方法有默认实现,现有代码无需修改
  • 多重继承:提供了一种有限的多重继承机制
  • API设计:可以定义通用的默认行为

7. 方法引用

7.1 是什么(What)

方法引用是Lambda表达式的一种简化写法,它允许直接引用已有的方法。当Lambda表达式只是调用一个已存在的方法时,可以使用方法引用来简化代码。

核心概念:

  • 方法引用:直接引用已有方法的语法糖
  • 类型推断:编译器自动推断方法引用类型
  • 性能优化:比Lambda表达式更高效
  • 代码简洁:减少样板代码

7.2 为什么(Why)

解决的问题:

  • 代码简洁性:避免编写简单的Lambda表达式
  • 可读性提升:方法引用比Lambda表达式更直观
  • 性能优化:编译器可以更好地优化方法引用
  • 代码复用:直接引用现有的方法
  • 类型安全:编译时类型检查

7.3 怎么做(How)

方法引用类型
import java.util.*;
import java.util.function.*;public class MethodReferenceExample {public static void main(String[] args) {List<String> names = Arrays.asList("Alice", "Bob", "Charlie");// 1. 静态方法引用names.forEach(System.out::println);// 2. 实例方法引用(特定对象)String prefix = "Hello, ";names.forEach(prefix::concat);// 3. 实例方法引用(任意对象)names.forEach(String::toUpperCase);// 4. 构造方法引用List<String> upperNames = names.stream().map(String::toUpperCase).collect(Collectors.toList());// 5. 数组构造方法引用Function<Integer, String[]> arrayCreator = String[]::new;String[] array = arrayCreator.apply(5);}
}
详细示例
public class MethodReferenceDetailedExample {public static void main(String[] args) {// 静态方法引用Function<String, Integer> parseInt = Integer::parseInt;System.out.println("解析数字: " + parseInt.apply("123"));// 实例方法引用(特定对象)String prefix = "User: ";Function<String, String> addPrefix = prefix::concat;System.out.println("添加前缀: " + addPrefix.apply("Alice"));// 实例方法引用(任意对象)Function<String, String> toUpper = String::toUpperCase;System.out.println("转大写: " + toUpper.apply("hello"));// 构造方法引用Supplier<StringBuilder> sbCreator = StringBuilder::new;StringBuilder sb = sbCreator.get();sb.append("Hello");System.out.println("StringBuilder: " + sb);// 数组构造方法引用IntFunction<int[]> arrayCreator = int[]::new;int[] numbers = arrayCreator.apply(5);System.out.println("数组长度: " + numbers.length);}
}
Java 8前后的对比

对比1:Lambda表达式 vs 方法引用

import java.util.*;
import java.util.function.*;public class LambdaVsMethodReferenceComparison {public static void main(String[] args) {List<String> names = Arrays.asList("Alice", "Bob", "Charlie");// Java 8:Lambda表达式System.out.println("=== Lambda表达式 ===");names.forEach(name -> System.out.println(name));names.stream().map(name -> name.toUpperCase()).forEach(name -> System.out.println(name));// Java 8:方法引用(更简洁)System.out.println("\n=== 方法引用 ===");names.forEach(System.out::println);names.stream().map(String::toUpperCase).forEach(System.out::println);// 对比:构造方法System.out.println("\n=== 构造方法对比 ===");// Lambda方式Supplier<StringBuilder> sbLambda = () -> new StringBuilder();// 方法引用方式Supplier<StringBuilder> sbMethodRef = StringBuilder::new;System.out.println("Lambda创建: " + sbLambda.get());System.out.println("方法引用创建: " + sbMethodRef.get());}
}

对比2:传统匿名内部类 vs 方法引用

public class AnonymousVsMethodReferenceComparison {public static void main(String[] args) {List<String> names = Arrays.asList("Alice", "Bob", "Charlie");// Java 8之前:匿名内部类System.out.println("=== Java 8之前:匿名内部类 ===");names.forEach(new Consumer<String>() {@Overridepublic void accept(String name) {System.out.println("Hello, " + name);}});// Java 8:Lambda表达式System.out.println("\n=== Java 8:Lambda表达式 ===");names.forEach(name -> System.out.println("Hello, " + name));// Java 8:方法引用(最简洁)System.out.println("\n=== Java 8:方法引用 ===");names.forEach(name -> System.out.println("Hello, " + name));// 自定义方法引用names.forEach(this::greet);}private void greet(String name) {System.out.println("Greetings, " + name);}
}

对比3:函数式接口实现

public class FunctionalInterfaceComparison {public static void main(String[] args) {// Java 8之前:需要创建完整的实现类System.out.println("=== Java 8之前:完整实现类 ===");Comparator<String> oldComparator = new Comparator<String>() {@Overridepublic int compare(String s1, String s2) {return s1.compareTo(s2);}};List<String> names = Arrays.asList("Charlie", "Alice", "Bob");names.sort(oldComparator);System.out.println("排序结果: " + names);// Java 8:Lambda表达式System.out.println("\n=== Java 8:Lambda表达式 ===");List<String> names2 = Arrays.asList("Charlie", "Alice", "Bob");names2.sort((s1, s2) -> s1.compareTo(s2));System.out.println("排序结果: " + names2);// Java 8:方法引用(最简洁)System.out.println("\n=== Java 8:方法引用 ===");List<String> names3 = Arrays.asList("Charlie", "Alice", "Bob");names3.sort(String::compareTo);System.out.println("排序结果: " + names3);// 性能对比System.out.println("\n=== 性能对比 ===");long startTime = System.currentTimeMillis();for (int i = 0; i < 1000000; i++) {names.sort(oldComparator);}long endTime = System.currentTimeMillis();System.out.println("匿名内部类耗时: " + (endTime - startTime) + "ms");startTime = System.currentTimeMillis();for (int i = 0; i < 1000000; i++) {names2.sort((s1, s2) -> s1.compareTo(s2));}endTime = System.currentTimeMillis();System.out.println("Lambda表达式耗时: " + (endTime - startTime) + "ms");startTime = System.currentTimeMillis();for (int i = 0; i < 1000000; i++) {names3.sort(String::compareTo);}endTime = System.currentTimeMillis();System.out.println("方法引用耗时: " + (endTime - startTime) + "ms");}
}// 自定义类的方法引用示例
class Person {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}public String getName() { return name; }public int getAge() { return age; }public static int compareByAge(Person a, Person b) {return Integer.compare(a.age, b.age);}public static Person create(String name, int age) {return new Person(name, age);}@Overridepublic String toString() {return name + "(" + age + ")";}
}class MethodReferenceCustomExample {public static void main(String[] args) {List<Person> people = Arrays.asList(new Person("Alice", 25),new Person("Bob", 30),new Person("Charlie", 20));// 静态方法引用people.sort(Person::compareByAge);System.out.println("按年龄排序: " + people);// 构造方法引用BiFunction<String, Integer, Person> personCreator = Person::new;Person newPerson = personCreator.apply("David", 35);System.out.println("新创建的人: " + newPerson);// 实例方法引用Function<Person, String> getName = Person::getName;people.stream().map(getName).forEach(System.out::println);}
}

8. CompletableFuture

8.1 是什么(What)

CompletableFuture是Java 8引入的一个异步编程工具,它实现了Future接口,并提供了更强大的异步编程能力。它支持异步任务的组合、异常处理、超时控制等高级功能。

核心概念:

  • 异步执行:支持异步任务的创建和执行
  • 任务组合:可以组合多个异步任务
  • 异常处理:内置异常处理机制
  • 回调机制:支持完成后的回调处理
  • 线程池集成:与ExecutorService无缝集成

8.2 为什么(Why)

解决的问题:

  • 异步编程复杂性:简化异步任务的编写和管理
  • 任务组合困难:传统Future难以组合多个异步任务
  • 异常处理复杂:异步任务的异常处理更加困难
  • 回调地狱:避免嵌套回调导致的代码可读性问题
  • 性能提升:支持并行执行和任务组合

8.3 怎么做(How)

基本用法
import java.util.concurrent.*;
import java.util.function.*;public class CompletableFutureBasicExample {public static void main(String[] args) throws Exception {// 创建异步任务CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(1000);return "异步任务完成";} catch (InterruptedException e) {return "任务被中断";}});// 等待结果String result = future.get();System.out.println("结果: " + result);// 异步处理结果CompletableFuture<String> processed = future.thenApply(str -> str + " - 已处理");System.out.println("处理后的结果: " + processed.get());// 异步消费结果CompletableFuture<Void> consumed = future.thenAccept(str -> System.out.println("消费结果: " + str));consumed.get(); // 等待消费完成}
}
高级用法
public class CompletableFutureAdvancedExample {public static void main(String[] args) throws Exception {// 任务组合CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "任务1");CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> "任务2");CompletableFuture<String> task3 = CompletableFuture.supplyAsync(() -> "任务3");// 等待所有任务完成CompletableFuture<Void> allTasks = CompletableFuture.allOf(task1, task2, task3);allTasks.get();System.out.println("所有任务完成: " + task1.get() + ", " + task2.get() + ", " + task3.get());// 等待任一任务完成CompletableFuture<Object> anyTask = CompletableFuture.anyOf(task1, task2, task3);System.out.println("任一任务完成: " + anyTask.get());// 异常处理CompletableFuture<String> errorTask = CompletableFuture.supplyAsync(() -> {if (true) throw new RuntimeException("模拟异常");return "成功";}).exceptionally(throwable -> "异常处理: " + throwable.getMessage());System.out.println("异常处理结果: " + errorTask.get());// 超时控制CompletableFuture<String> timeoutTask = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(3000);return "长时间任务";} catch (InterruptedException e) {return "被中断";}}).orTimeout(2, TimeUnit.SECONDS).exceptionally(throwable -> "超时: " + throwable.getMessage());System.out.println("超时控制结果: " + timeoutTask.get());}
}
实际应用场景
public class CompletableFuturePracticalExample {public static void main(String[] args) throws Exception {// 模拟用户服务CompletableFuture<String> userInfo = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(100);return "用户信息";} catch (InterruptedException e) {throw new RuntimeException(e);}});// 模拟订单服务CompletableFuture<String> orderInfo = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(150);return "订单信息";} catch (InterruptedException e) {throw new RuntimeException(e);}});// 模拟商品服务CompletableFuture<String> productInfo = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(200);return "商品信息";} catch (InterruptedException e) {throw new RuntimeException(e);}});// 组合所有服务结果CompletableFuture<String> combinedResult = userInfo.thenCombine(orderInfo, (user, order) -> user + " + " + order).thenCombine(productInfo, (combined, product) -> combined + " + " + product);System.out.println("组合结果: " + combinedResult.get());// 异步处理结果CompletableFuture<String> processedResult = combinedResult.thenApplyAsync(result -> "处理后的: " + result).thenApplyAsync(result -> result + " - 完成");System.out.println("最终结果: " + processedResult.get());}
}
Java 8前后的对比

对比1:异步任务创建

import java.util.concurrent.*;
import java.util.function.*;public class AsyncTaskCreationComparison {public static void main(String[] args) throws Exception {// Java 8之前:使用ExecutorService和FutureSystem.out.println("=== Java 8之前:ExecutorService + Future ===");ExecutorService executor = Executors.newFixedThreadPool(2);Future<String> future1 = executor.submit(new Callable<String>() {@Overridepublic String call() throws Exception {Thread.sleep(1000);return "任务1完成";}});Future<String> future2 = executor.submit(new Callable<String>() {@Overridepublic String call() throws Exception {Thread.sleep(1500);return "任务2完成";}});// 等待结果String result1 = future1.get();String result2 = future2.get();System.out.println("结果1: " + result1);System.out.println("结果2: " + result2);executor.shutdown();// Java 8:使用CompletableFutureSystem.out.println("\n=== Java 8:CompletableFuture ===");CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(1000);return "任务1完成";} catch (InterruptedException e) {return "任务1被中断";}});CompletableFuture<String> cf2 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(1500);return "任务2完成";} catch (InterruptedException e) {return "任务2被中断";}});// 等待结果String cfResult1 = cf1.get();String cfResult2 = cf2.get();System.out.println("结果1: " + cfResult1);System.out.println("结果2: " + cfResult2);}
}

对比2:任务组合

public class TaskCombinationComparison {public static void main(String[] args) throws Exception {// Java 8之前:手动组合任务System.out.println("=== Java 8之前:手动组合 ===");ExecutorService executor = Executors.newFixedThreadPool(3);// 创建三个任务Future<String> task1 = executor.submit(() -> {Thread.sleep(100);return "用户信息";});Future<String> task2 = executor.submit(() -> {Thread.sleep(150);return "订单信息";});Future<String> task3 = executor.submit(() -> {Thread.sleep(200);return "商品信息";});// 手动等待所有任务完成String result1 = task1.get();String result2 = task2.get();String result3 = task3.get();// 手动组合结果String combined = result1 + " + " + result2 + " + " + result3;System.out.println("组合结果: " + combined);executor.shutdown();// Java 8:使用CompletableFuture组合System.out.println("\n=== Java 8:CompletableFuture组合 ===");CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(100);return "用户信息";} catch (InterruptedException e) {return "用户信息获取失败";}});CompletableFuture<String> cf2 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(150);return "订单信息";} catch (InterruptedException e) {return "订单信息获取失败";}});CompletableFuture<String> cf3 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(200);return "商品信息";} catch (InterruptedException e) {return "商品信息获取失败";}});// 自动组合所有任务CompletableFuture<String> combinedCF = CompletableFuture.allOf(cf1, cf2, cf3).thenApply(v -> {try {return cf1.get() + " + " + cf2.get() + " + " + cf3.get();} catch (Exception e) {return "组合失败";}});System.out.println("组合结果: " + combinedCF.get());}
}

对比3:异常处理

public class ExceptionHandlingComparison {public static void main(String[] args) throws Exception {// Java 8之前:手动异常处理System.out.println("=== Java 8之前:手动异常处理 ===");ExecutorService executor = Executors.newSingleThreadExecutor();Future<String> future = executor.submit(new Callable<String>() {@Overridepublic String call() throws Exception {if (Math.random() > 0.5) {throw new RuntimeException("模拟异常");}return "成功";}});try {String result = future.get();System.out.println("结果: " + result);} catch (ExecutionException e) {System.out.println("异常: " + e.getCause().getMessage());}executor.shutdown();// Java 8:使用CompletableFuture异常处理System.out.println("\n=== Java 8:CompletableFuture异常处理 ===");CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {if (Math.random() > 0.5) {throw new RuntimeException("模拟异常");}return "成功";}).exceptionally(throwable -> "异常处理: " + throwable.getMessage());String cfResult = cf.get();System.out.println("结果: " + cfResult);// 更高级的异常处理CompletableFuture<String> cfAdvanced = CompletableFuture.supplyAsync(() -> {if (Math.random() > 0.5) {throw new RuntimeException("模拟异常");}return "成功";}).handle((result, throwable) -> {if (throwable != null) {return "异常处理: " + throwable.getMessage();}return "处理结果: " + result;});String cfAdvancedResult = cfAdvanced.get();System.out.println("高级处理结果: " + cfAdvancedResult);}
}

9. Nashorn JavaScript引擎

9.1 是什么(What)

Nashorn是Java 8引入的JavaScript引擎,它完全用Java编写,运行在JVM上。它允许在Java应用程序中执行JavaScript代码,提供了Java和JavaScript之间的互操作性。

核心概念:

  • JavaScript引擎:在JVM上执行JavaScript代码
  • Java集成:Java和JavaScript之间的双向调用
  • 性能优化:比Rhino引擎性能更好
  • 标准支持:支持ECMAScript 5.1标准

9.2 为什么(Why)

解决的问题:

  • 脚本集成:在Java应用中集成JavaScript脚本
  • 动态配置:支持运行时配置和规则引擎
  • 插件系统:为Java应用提供插件扩展能力
  • 原型开发:快速原型开发和测试
  • 跨语言互操作:Java和JavaScript的互操作性

9.3 怎么做(How)

基本用法
import javax.script.*;
import java.io.*;public class NashornExample {public static void main(String[] args) throws Exception {// 创建脚本引擎ScriptEngineManager manager = new ScriptEngineManager();ScriptEngine engine = manager.getEngineByName("nashorn");// 执行简单JavaScript代码Object result = engine.eval("var x = 10; var y = 20; x + y;");System.out.println("JavaScript计算结果: " + result);// 执行JavaScript函数engine.eval("function add(a, b) { return a + b; }");Invocable invocable = (Invocable) engine;Object sum = invocable.invokeFunction("add", 15, 25);System.out.println("函数调用结果: " + sum);// 从文件加载JavaScripttry (Reader reader = new FileReader("script.js")) {engine.eval(reader);} catch (FileNotFoundException e) {System.out.println("脚本文件未找到,使用内联脚本");engine.eval("function greet(name) { return 'Hello, ' + name + '!'; }");}Object greeting = invocable.invokeFunction("greet", "World");System.out.println("问候语: " + greeting);}
}
Java与JavaScript互操作
public class JavaJavaScriptInterop {public static void main(String[] args) throws Exception {ScriptEngineManager manager = new ScriptEngineManager();ScriptEngine engine = manager.getEngineByName("nashorn");// 将Java对象传递给JavaScriptengine.put("javaList", Arrays.asList("Java", "JavaScript", "Python"));engine.eval("var jsArray = javaList.toArray();");engine.eval("for (var i = 0; i < jsArray.length; i++) { print(jsArray[i]); }");// 从JavaScript调用Java方法engine.eval("var javaSystem = Java.type('java.lang.System');");engine.eval("javaSystem.out.println('从JavaScript调用Java方法');");// 创建Java对象engine.eval("var date = new java.util.Date();");engine.eval("print('当前时间: ' + date);");// 使用Java集合engine.eval("var map = new java.util.HashMap();");engine.eval("map.put('key1', 'value1');");engine.eval("map.put('key2', 'value2');");engine.eval("print('Map大小: ' + map.size());");}
}
Java 8前后的对比

对比1:脚本执行方式

import javax.script.*;
import java.io.*;public class ScriptExecutionComparison {public static void main(String[] args) throws Exception {// Java 8之前:使用Rhino引擎(需要单独引入)System.out.println("=== Java 8之前:Rhino引擎 ===");try {// 注意:Rhino引擎在Java 8之前需要单独引入// ScriptEngineManager manager = new ScriptEngineManager();// ScriptEngine engine = manager.getEngineByName("rhino");System.out.println("Rhino引擎需要单独引入,配置复杂");} catch (Exception e) {System.out.println("Rhino引擎不可用: " + e.getMessage());}// Java 8:内置Nashorn引擎System.out.println("\n=== Java 8:内置Nashorn引擎 ===");ScriptEngineManager manager = new ScriptEngineManager();ScriptEngine engine = manager.getEngineByName("nashorn");if (engine != null) {System.out.println("Nashorn引擎可用");// 执行简单JavaScriptObject result = engine.eval("var x = 10; var y = 20; x + y;");System.out.println("JavaScript计算结果: " + result);} else {System.out.println("Nashorn引擎不可用");}}
}

对比2:性能对比

public class PerformanceComparison {public static void main(String[] args) throws Exception {ScriptEngineManager manager = new ScriptEngineManager();ScriptEngine engine = manager.getEngineByName("nashorn");if (engine == null) {System.out.println("Nashorn引擎不可用");return;}// 测试JavaScript执行性能System.out.println("=== JavaScript执行性能测试 ===");// 简单计算long startTime = System.currentTimeMillis();for (int i = 0; i < 10000; i++) {engine.eval("var x = " + i + "; var y = " + (i * 2) + "; x + y;");}long endTime = System.currentTimeMillis();System.out.println("简单计算耗时: " + (endTime - startTime) + "ms");// 函数调用engine.eval("function add(a, b) { return a + b; }");startTime = System.currentTimeMillis();Invocable invocable = (Invocable) engine;for (int i = 0; i < 10000; i++) {invocable.invokeFunction("add", i, i * 2);}endTime = System.currentTimeMillis();System.out.println("函数调用耗时: " + (endTime - startTime) + "ms");// 对比Java原生性能System.out.println("\n=== Java原生性能对比 ===");startTime = System.currentTimeMillis();for (int i = 0; i < 10000; i++) {int x = i;int y = i * 2;int result = x + y;}endTime = System.currentTimeMillis();System.out.println("Java原生计算耗时: " + (endTime - startTime) + "ms");}
}

对比3:集成复杂度

public class IntegrationComplexityComparison {public static void main(String[] args) throws Exception {// Java 8之前:复杂的脚本集成System.out.println("=== Java 8之前:复杂集成 ===");System.out.println("1. 需要单独引入脚本引擎依赖");System.out.println("2. 需要配置类路径和依赖");System.out.println("3. 版本兼容性问题");System.out.println("4. 性能优化困难");System.out.println("5. 调试和错误处理复杂");// Java 8:内置集成System.out.println("\n=== Java 8:内置集成 ===");System.out.println("1. 内置Nashorn引擎,无需额外依赖");System.out.println("2. 与JDK版本完全兼容");System.out.println("3. 性能经过优化");System.out.println("4. 错误处理更加友好");System.out.println("5. 调试支持更好");// 实际演示try {ScriptEngineManager manager = new ScriptEngineManager();ScriptEngine engine = manager.getEngineByName("nashorn");if (engine != null) {System.out.println("\n=== 实际集成演示 ===");// 执行配置脚本engine.eval("var config = { timeout: 5000, retries: 3 };");engine.eval("print('配置加载成功: ' + JSON.stringify(config));");// 动态配置Java对象engine.put("javaSystem", System.class);engine.eval("javaSystem.out.println('从JavaScript调用Java成功');");System.out.println("集成成功!");}} catch (Exception e) {System.out.println("集成失败: " + e.getMessage());}}
}

10. 总结与最佳实践

10.1 是什么(What)

Java 8的发布标志着Java语言的一个重要转折点,从纯面向对象语言转向支持函数式编程的混合范式。

核心价值:

  • 函数式编程:支持Lambda表达式和函数式接口
  • 流式处理:Stream API提供声明式数据处理
  • 异步编程:CompletableFuture简化异步任务
  • 空值安全:Optional类提供空值处理
  • 现代日期时间:新的日期时间API
  • 代码简洁性:大幅减少样板代码,提高开发效率

10.2 为什么(Why)

解决的问题:

  • 编程范式转变:从纯面向对象转向函数式编程
  • 代码质量提升:减少样板代码,提高可读性
  • 性能优化:新的API设计带来更好的性能
  • 开发效率:简化常见编程任务
  • 现代化:跟上编程语言发展趋势

10.3 怎么做(How)

最佳实践建议
Lambda表达式使用建议
// 好的实践
names.stream().filter(name -> name.length() > 3).map(String::toUpperCase).forEach(System.out::println);// 避免过度复杂的Lambda
names.stream().filter(name -> {// 避免在Lambda中写复杂逻辑if (name == null) return false;if (name.length() < 2) return false;return name.matches("[a-zA-Z]+");}).forEach(System.out::println);
Stream API使用建议
// 优先使用Stream API
List<String> result = names.stream().filter(name -> name.startsWith("A")).collect(Collectors.toList());// 避免过度使用Stream
// 简单循环用传统for循环更清晰
for (String name : names) {if (name.startsWith("A")) {System.out.println(name);}
}
Optional使用建议
// 好的实践
Optional.ofNullable(user).map(User::getName).orElse("Unknown");// 避免反模式
Optional<String> name = Optional.of("value");
if (name.isPresent()) {String value = name.get(); // 反模式
}
性能考虑
  1. Stream vs 传统循环:简单操作用传统循环,复杂操作用Stream
  2. 并行流使用:数据量大且操作独立时使用并行流
  3. 方法引用:优先使用方法引用而不是Lambda表达式
  4. 延迟执行:Stream的中间操作不会立即执行,注意性能影响
迁移策略
  1. 渐进式迁移:逐步将现有代码迁移到Java 8特性
  2. 团队培训:确保团队成员熟悉新特性的使用
  3. 代码审查:在代码审查中关注新特性的正确使用
  4. 性能测试:迁移后进行性能测试,确保性能提升
未来展望

Java 8的成功为后续版本奠定了基础:

  • Java 9:模块系统、REPL工具
  • Java 10:局部变量类型推断
  • Java 11:长期支持版本
  • Java 17:下一个长期支持版本

结语

Java 8的发布是Java发展史上的一个重要里程碑,它引入了许多革命性的特性,彻底改变了Java的编程范式。通过Lambda表达式、Stream API、Optional类等新特性,Java变得更加现代化、高效和易用。

掌握这些特性不仅能够提高开发效率,还能写出更加优雅、可维护的代码。希望本文能够帮助您深入理解Java 8的核心特性,并在实际项目中灵活运用。


📚 参考文档与扩展阅读

官方文档

  • Oracle Java 8 官方文档

    • Java SE 8 Documentation
    • Java SE 8 API Specification
    • What’s New in JDK 8
  • Oracle Java Tutorials

    • Lambda Expressions Tutorial
    • Aggregate Operations Tutorial
    • Date Time API Tutorial

技术规范 (JSR)

  • JSR 335: Lambda Expressions for the Java Programming Language
  • JSR 310: Date and Time API
  • JSR 223: Scripting for the Java Platform

权威书籍

  • 《Java 8 in Action》 - Raoul-Gabriel Urma, Mario Fusco, Alan Mycroft
  • 《Modern Java in Action》 - Raoul-Gabriel Urma, Mario Fusco, Alan Mycroft
  • 《Effective Java (Third Edition)》 - Joshua Bloch
  • 《Java: The Complete Reference (Eleventh Edition)》 - Herbert Schildt
  • 《Java 8函数式编程》 - Richard Warburton

在线教程与博客

  • Baeldung Java 8 系列

    • Java 8 Lambda Expressions
    • Java 8 Stream API
    • Java 8 Optional
  • Oracle官方博客

    • Java 8 Friday Series
    • The Java Tutorials Blog

实践项目与示例

  • GitHub项目
    • Java 8 Examples
    • Modern Java Examples
    • Stream API Examples

性能与最佳实践

  • 性能分析文章

    • “Java 8 Stream Performance” - Vladimir Gitlevich
    • “Lambda Expression Performance” - Sergey Kuksenko
    • “Java 8 Parallel Streams Performance” - Michael Vorburger
  • 最佳实践指南

    • Oracle Java 8 Best Practices
    • Google Java Style Guide
http://www.xdnf.cn/news/1389313.html

相关文章:

  • lesson49:HTML基础标签全解析:从入门到精通的网页构建指南
  • SQL Server 查看备份计划
  • Cursor不能读取.env文件解决办法(**/.env、**/env.*)
  • 华为认证全解析:价值详解、含金量解读(2025最新版)
  • 安全月报 | 傲盾DDoS攻击防御2025年8月简报
  • CRYPT32!CryptMsgUpdate函数分析之CRYPT32!PkiAsn1Decode函数的作用是得到pci
  • 达梦数据库-归档日志(一)
  • JavaScript 入门教程
  • 《Linux 网络编程六:数据存储与SQLite应用指南》
  • TF-IDF:文本分析的“火眼金睛”
  • PCIe 6.0 TLP路由机制:解密高效数据传输的核心架构
  • 【微知】如何撤销一个git的commit?以及撤销的3种方式?
  • 在本地获取下载chrome,然后离线搬运到 ECS
  • 最小生成树——Kruskal
  • go 使用rabbitMQ
  • 【谷歌浏览器】浏览器实用自用版——谷歌浏览器(Google Chrome)离线纯净版安装 官方版无任何捆绑及广告 【离线安装谷歌浏览器】
  • 通过 KafkaMQ 接入Skywalking 数据最佳实践
  • R ggplot2学习Nature子刊一张图,换数据即可用!
  • leetcode 338 比特位计数
  • 04数据库约束实战:从入门到精通
  • Linux下的网络编程SQLITE3详解
  • 算法题打卡力扣第1004. 最大连续1的个数 III(mid)
  • 技术速递|新手指南:如何在 Foundry Local 中使用自定义模型
  • 百度后端岗位--面试真题分析
  • CCS的诡异报错合集1(以C2000为例)
  • MAC spotlight 搜不到应用程序和 tags 生效
  • ZooKeeper 安装配置
  • C++基础(②VS2022创建项目)
  • 球型摄像机实现360°无死角
  • CLion 中配置运行 Qt 项目指南