课程导言:编程范式的革命
"函数式编程不是新概念,但它在Java中的引入彻底改变了我们处理数据的方式——从命令式操作到声明式表达的转变!"
函数式思维类比
命令式编程:像烹饪手册 - "先切菜,再热油,然后翻炒..."
函数式编程:像高级餐厅点餐 - "请给我一份宫保鸡丁"(不关心如何制作)
Ⅰ. Lambda表达式:简洁的函数
1.1 从匿名类到Lambda
// 传统方式:匿名内部类Runnable oldRunnable = new Runnable() {@Overridepublic void run() {System.out.println("Hello World");}};// Lambda方式Runnable lambdaRunnable = () -> System.out.println("Hello Lambda");
1.2 Lambda语法精要
// 无参函数() -> System.out.println("无参");// 单参函数(可省略括号)name -> System.out.println("Hello " + name);// 多参函数(x, y) -> x + y;// 代码块(name, age) -> {String info = name + ":" + age;return info;};
Ⅱ. 函数式接口:Lambda的类型
2.1 核心函数式接口
Supplier<T> | () -> "data" | |||
Consumer<T> | s -> System.out.println(s) | |||
Function<T,R> | s -> s.length() | |||
Predicate<T> | s -> s.isEmpty() | |||
BiFunction<T,U,R> | (a,b) -> a + b |
2.2 自定义函数式接口
@FunctionalInterfaceinterface TriFunction<T,U,V,R> {R apply(T t, U u, V v);}// 使用TriFunction<Integer, Integer, Integer, Integer> sumThree =(a, b, c) -> a + b + c;int result = sumThree.apply(1, 2, 3); // 6
Ⅲ. 方法引用:语法糖的魔法
3.1 四种方法引用类型
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");// 1. 静态方法引用names.forEach(System.out::println);// 2. 实例方法引用String prefix = "Name: ";names.forEach(prefix::concat);// 3. 任意对象方法引用names.sort(String::compareToIgnoreCase);// 4. 构造器引用Supplier<List<String>> listSupplier = ArrayList::new;List<String> newList = listSupplier.get();
Ⅳ. Stream API:流式数据处理
4.1 流操作三阶段

4.2 流操作实战
List<Person> people = Arrays.asList(new Person("Alice", 25, "London"),new Person("Bob", 30, "New York"),new Person("Charlie", 20, "London"));// 流处理:找出伦敦居民的平均年龄double averageAge = people.stream().filter(p -> "London".equals(p.getCity())) // 过滤.mapToInt(Person::getAge) // 转换.average() // 聚合.orElse(0); // 默认值System.out.println("伦敦居民平均年龄: " + averageAge);
4.3 常用流操作
stream()parallelStream(), Stream.of() | ||
filter()map(), flatMap(), distinct(), sorted(), peek() | ||
forEach()collect(), reduce(), count(), min(), max(), anyMatch() |
Ⅴ. 高级流技巧
5.1 流分组与分区
// 按城市分组Map<String, List<Person>> peopleByCity = people.stream().collect(Collectors.groupingBy(Person::getCity));// 按年龄分区(<30和>=30)Map<Boolean, List<Person>> partitionByAge = people.stream().collect(Collectors.partitioningBy(p -> p.getAge() < 30));
5.2 流扁平化处理
List<List<Integer>> numberLists = Arrays.asList(Arrays.asList(1, 2, 3),Arrays.asList(4, 5, 6),Arrays.asList(7, 8, 9));// 扁平化为单个流List<Integer> allNumbers = numberLists.stream().flatMap(List::stream).collect(Collectors.toList()); // [1,2,3,4,5,6,7,8,9]
5.3 自定义收集器
// 收集为自定义对象public class Statistics {private int count;private int sum;// 构造器/getter/setter}Statistics stats = people.stream().mapToInt(Person::getAge).collect(Statistics::new,(s, age) -> { s.setCount(s.getCount()+1); s.setSum(s.getSum()+age); },(s1, s2) -> { s1.setCount(s1.getCount()+s2.getCount());s1.setSum(s1.getSum()+s2.getSum()); });
Ⅵ. 并行流:性能加速器
6.1 并行流使用
long start = System.currentTimeMillis();// 顺序流long sequentialCount = IntStream.range(0, 1_000_000).filter(n -> n % 3 == 0).count();// 并行流long parallelCount = IntStream.range(0, 1_000_000).parallel() // 只需添加此调用.filter(n -> n % 3 == 0).count();System.out.println("顺序耗时: " + (System.currentTimeMillis()-start) + "ms");System.out.println("并行耗时: " + (System.currentTimeMillis()-start) + "ms");
6.2 并行流注意事项
状态依赖操作:避免共享可变状态
数据规模:小数据量可能更慢(线程开销)
数据结构拆分成本:
高效:ArrayList、数组
低效:LinkedList、HashSet
Ⅶ. 函数式实战:现代Java编程
7.1 资源自动管理
// 传统try-with-resourcestry (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {// 使用资源}// 函数式增强public static void useResource(Consumer<BufferedReader> consumer) {try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {consumer.accept(br);} catch (IOException e) {e.printStackTrace();}}// 使用useResource(br -> {br.lines().forEach(System.out::println);});
7.2 函数式事件处理
// 事件发布器class EventBus {private Map<String, List<Consumer<Object>>> handlers = new HashMap<>();public void on(String eventType, Consumer<Object> handler) {handlers.computeIfAbsent(eventType, k -> new ArrayList<>()).add(handler);}public void emit(String eventType, Object data) {handlers.getOrDefault(eventType, Collections.emptyList()).forEach(handler -> handler.accept(data));}}// 使用EventBus bus = new EventBus();bus.on("login", user -> System.out.println("用户登录: " + user));bus.emit("login", "Alice");
函数式编程最佳实践
避免副作用:
// 错误:在lambda中修改外部状态int[] counter = {0};list.forEach(s -> counter[0]++);// 正确:使用reducelong count = list.stream().count();
方法引用优先:
// 优于 s -> s.length()list.stream().map(String::length)
流延迟执行:
// 无终止操作,中间操作不会执行Stream<String> stream = list.stream().filter(s -> {System.out.println("过滤: " + s); // 不会输出return s.length() > 3;});
课程总结:函数式三大魔法
Lambda表达式:
简洁的函数表示
替代匿名内部类
Stream API:

3.并行处理:
轻松利用多核
自动任务拆分
课后挑战
数据转换器:
List<String> input = Arrays.asList("1", "2", "3");// 转换为List<Integer> [1,2,3]
单词频率统计:
String text = "hello world hello java";// 生成Map: {hello=2, world=1, java=1}
文件处理系统:
// 读取文件,找出长度>10的行,去重后排序Files.lines(Paths.get("data.txt")).filter(line -> line.length() > 10).distinct().sorted().forEach(System.out::println);
下节课预告:《Java模块系统:Jigsaw拼图》
你将学到:
模块化编程的必要性
module-info.java详解
模块的声明与依赖
服务与实现的解耦
模块化应用的打包与分发
迁移现有应用到模块系统
"函数式编程不是万能的,但它为数据处理提供了优雅而强大的工具。掌握Lambda和Stream,你将写出更简洁、更易读、更高效的Java代码!"

文章转载自让天下没有难学的编程,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




