暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Java函数式编程:Lambda与Stream的魔法

课程导言:编程范式的革命

"函数式编程不是新概念,但它在Java中的引入彻底改变了我们处理数据的方式——从命令式操作到声明式表达的转变!"

函数式思维类比

  • 命令式编程:像烹饪手册 - "先切菜,再热油,然后翻炒..."

  • 函数式编程:像高级餐厅点餐 - "请给我一份宫保鸡丁"(不关心如何制作)

Ⅰ. Lambda表达式:简洁的函数

1.1 从匿名类到Lambda

    // 传统方式:匿名内部类
    Runnable oldRunnable = new Runnable() {
        @Override
        public 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>
      0
      T
      提供值
      () -> "data"
      Consumer<T>
      1
      void
      消费值
      s -> System.out.println(s)
      Function<T,R>
      1
      R
      转换值
      s -> s.length()
      Predicate<T>
      1
      boolean
      条件判断
      s -> s.isEmpty()
      BiFunction<T,U,R>
      2
      R
      双参转换
      (a,b) -> a + b

      2.2 自定义函数式接口

        @FunctionalInterface
        interface TriFunction<T,U,V,R> {
            apply(T t, U u, V v);
        }
        // 使用
        TriFunction<Integer, Integer, Integer, Integer> sumThree = 
            (a, b, c) -> a + b + c;
        int result = sumThree.apply(123); // 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<StringList<Person>> peopleByCity = people.stream()
                  .collect(Collectors.groupingBy(Person::getCity));
              // 按年龄分区(<30和>=30)
              Map<BooleanList<Person>> partitionByAge = people.stream()
                  .collect(Collectors.partitioningBy(p -> p.getAge() < 30));

              5.2 流扁平化处理

                List<List<Integer>> numberLists = Arrays.asList(
                    Arrays.asList(123),
                    Arrays.asList(456),
                    Arrays.asList(789)
                );
                // 扁平化为单个流
                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(01_000_000)
                        .filter(n -> n % 3 == 0)
                        .count();
                    // 并行流
                    long parallelCount = IntStream.range(01_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 并行流注意事项

                    1. 状态依赖操作:避免共享可变状态

                    2. 数据规模:小数据量可能更慢(线程开销)

                    3. 数据结构拆分成本

                      • 高效:ArrayList、数组

                      • 低效:LinkedList、HashSet

                    Ⅶ. 函数式实战:现代Java编程

                    7.1 资源自动管理

                      // 传统try-with-resources
                      try (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<StringList<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");

                        函数式编程最佳实践

                        1. 避免副作用

                          // 错误:在lambda中修改外部状态
                          int[] counter = {0};
                          list.forEach(s -> counter[0]++);
                          // 正确:使用reduce
                          long count = list.stream().count();
                          1. 方法引用优先

                            // 优于 s -> s.length()
                            list.stream().map(String::length)
                            1. 流延迟执行

                              // 无终止操作,中间操作不会执行
                              Stream<String> stream = list.stream().filter(s -> {
                                  System.out.println("过滤: " + s); // 不会输出
                                  return s.length() > 3;
                              });

                              课程总结:函数式三大魔法

                              1. Lambda表达式

                                • 简洁的函数表示

                                • 替代匿名内部类

                              2. Stream API

                              3.并行处理

                                • 轻松利用多核

                                • 自动任务拆分

                              课后挑战

                              1. 数据转换器

                                List<String> input = Arrays.asList("1""2""3");
                                // 转换为List<Integer> [1,2,3]
                                1. 单词频率统计

                                  String text = "hello world hello java";
                                  // 生成Map: {hello=2, world=1, java=1}
                                  1. 文件处理系统

                                    // 读取文件,找出长度>10的行,去重后排序
                                    Files.lines(Paths.get("data.txt"))
                                         .filter(line -> line.length() > 10)
                                         .distinct()
                                         .sorted()
                                         .forEach(System.out::println);

                                    下节课预告:《Java模块系统:Jigsaw拼图》

                                    你将学到:

                                    1. 模块化编程的必要性

                                    2. module-info.java详解

                                    3. 模块的声明与依赖

                                    4. 服务与实现的解耦

                                    5. 模块化应用的打包与分发

                                    6. 迁移现有应用到模块系统

                                    "函数式编程不是万能的,但它为数据处理提供了优雅而强大的工具。掌握Lambda和Stream,你将写出更简洁、更易读、更高效的Java代码!"

                                    新关注福利:送你100元优惠券,真能省!✨

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

                                    评论