前言

当你迷茫的时候,请点击 目录大纲 快速查看前面的技术文章,相信你总能找到前行的方向

另外,本文相关代码已上传 gitee仓库,欢迎关注收藏

函数式编程

函数式编程(Functional Programming,FP)是一种编程范式,它将计算视为数学函数的求值,并避免使用可变状态和可变数据。在Java中,函数式编程主要通过Lambda表达式方法引用来实现。

Java函数式编程的核心概念

函数式接口(Functional Interface)

定义一个抽象方法的接口,方法的就能以这个接口形式进行传参。

// 只有一个抽象方法的接口
@FunctionalInterface
public interface MyFunction {
int apply(int a, int b);
// 可以有默认方法
default void printResult(int result) {
System.out.println("结果: " + result);
}
// 可以有静态方法
static MyFunction add() {
return (a, b) -> a + b;
}
}

这样,函数可以当成一个普通参数进行传递,例如 MyFunction.add() 直接传参,在 func.apply(a, b) 使用方法参数调用加法。

public static void main(String[] args) {
// 函数式接口
doSomething(MyFunction.add(),2,3);
}
private static void doSomething(MyFunction func,int a,int b){
int res = func.apply(a, b); 	// 调用add()方法求 a+b
func.printResult(res); 			// MyFunction printResult 结果: 5
}

Lambda表达式

// 基本语法: (parameters) -> expression
// 或: (parameters) -> { statements; }
// 示例
public static void main(String[] args) {
Runnable runnable = () -> System.out.println("-1- runnable: Hello");
Thread t = new Thread(runnable);
t.start();
Comparator<Integer> comparator = (a, b) -> a - b;
  System.out.println("-2- comparator 排序:"+ Stream.of(9,5,6,3,4,2,1,8,7).sorted(comparator).collect(Collectors.toList()));
  MyFunction add = (a, b) -> a + b;
  MyFunction multiply = (a, b) -> a * b;
  System.out.println("-3- add.apply(2,3): " + add.apply(2, 3));
  System.out.println("-4- multiply.apply(2,3): " + multiply.apply(2, 3));
  }

结果如下:

-1- runnable: Hello
-2- comparator 排序:[1, 2, 3, 4, 5, 6, 7, 8, 9]
-3- add.apply(2,3): 5
-4- multiply.apply(2,3): 6

Java内置的函数式接口

常用函数式接口

private static void testCommFunction() {
// Predicate<T> - 接受一个参数,返回boolean
Predicate<String> isLong = s -> s.length() > 5;
  System.out.println(isLong.test("Hello")); // false
  // Function<T, R> - 接受一个参数,返回结果
    Function<String, Integer> stringLength = String::length;
      System.out.println(stringLength.apply("Hello")); // 5
      // Consumer<T> - 接受一个参数,无返回值
      Consumer<String> printer = System.out::println;
        printer.accept("Hello World");
        // Supplier<T> - 无参数,返回一个结果
        Supplier<Double> randomSupplier = Math::random;
          System.out.println(randomSupplier.get());
          // UnaryOperator<T> - 接受一个参数,返回同类型结果
          UnaryOperator<String> toUpper = String::toUpperCase;
            System.out.println(toUpper.apply("hello")); // HELLO
            // BinaryOperator<T> - 接受两个同类型参数,返回同类型结果
            BinaryOperator<Integer> sum = Integer::sum;
              System.out.println(sum.apply(5, 3)); // 8
              }

方法引用(Method Reference)

private static void testMethodRefFunction() {
List<String> names = Arrays.asList("Charlie", "Alice", "Bob", "\n");
  // 1. 静态方法引用
  names.forEach(System.out::println);
  // 2. 实例方法引用
  String prefix = "Hello, ";
  names.stream().map(prefix::concat).forEach(System.out::println);
  // 3. 特定类型的任意对象方法引用
  names.sort(String::compareToIgnoreCase);
  // 4. 构造方法引用
  names.stream()
  .map(String::new)
  .forEach(System.out::println);
  // 自定义方法用于方法引用
  System.out.println("\n过滤偶数:" + Stream.of(9, 5, 6, 3, 4, 2, 1, 8, 7).filter(Main::isEven).collect(Collectors.toList()));
  }
  public static boolean isEven(int number) {
  return number % 2 == 0;
  }

结果如下:

Charlie
Alice
Bob
Hello, Charlie
Hello, Alice
Hello, Bob
Hello,
Alice
Bob
Charlie
过滤偶数:[6, 4, 2, 8]

Stream API - 函数式编程的核心工具

Stream基本操作

public static void testStream() {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
  // 过滤和映射
  List<Integer> result = numbers.stream()
    .filter(n -> n % 2 == 0)        // 中间操作:过滤偶数
    .map(n -> n * n)               // 中间操作:平方
    .collect(Collectors.toList()); // 终端操作:收集结果
    System.out.println(result); // [4, 16, 36, 64, 100]
    // 更多操作
    numbers.stream()
    .distinct()                    // 去重
    .sorted()                      // 排序
    .limit(5)                      // 限制数量
    .skip(2)                       // 跳过前n个
    .forEach(System.out::println); // 遍历
    }

高级Stream操作

public static void testStream2() {
List<String> words = Arrays.asList("Hello", "World", "Java", "Stream");
  // 归约操作
  Optional<Integer> totalLength = words.stream()
    .map(String::length)
    .reduce(Integer::sum);
    System.out.println("总长度: " + totalLength.orElse(0));
    // 分组
    Map<Integer, List<String>> lengthMap = words.stream()
      .collect(Collectors.groupingBy(String::length));
      System.out.println("按长度分组: " + lengthMap);
      // 分区
      Map<Boolean, List<String>> partition = words.stream()
        .collect(Collectors.partitioningBy(s -> s.length() > 4));
        System.out.println("按长度分区: " + partition);
        // 连接字符串
        String joined = words.stream()
        .collect(Collectors.joining(", ", "[", "]"));
        System.out.println("连接结果: " + joined);
        }

结果如下:

总长度: 20
按长度分组: {4=[Java], 5=[Hello, World], 6=[Stream]}
按长度分区: {false=[Java], true=[Hello, World, Stream]}
连接结果: [Hello, World, Java, Stream]

Optional类 - 避免空指针异常

public static void testOptional() {
// 创建Optional
Optional<String> empty = Optional.empty();
  Optional<String> nonEmpty = Optional.of("Hello");
    Optional<String> nullable = Optional.ofNullable(null);
      // 使用Optional
      String result = nullable
      .map(String::toUpperCase)          // 如果值存在则转换
      .orElse("Default Value");         // 如果为空返回默认值
      System.out.println(result); // Default Value
      nullable.ifPresent(value -> System.out.println("值存在: " + value));
      // 链式操作
      Optional<String> finalResult = Optional.of(nonEmpty
        .filter(s -> s.length() > 3)
        .map(String::toUpperCase)
        .orElse("FALLBACK"));
        System.out.println(finalResult.get()); // HELLO
        }

函数组合和高阶函数

public static void testComposeFunction() {
// 函数组合
Function<Integer, Integer> multiplyBy2 = x -> x * 2;
  Function<Integer, Integer> add3 = x -> x + 3;
    // andThen: 先执行当前函数,再执行参数函数
    Function<Integer, Integer> multiplyAndAdd = multiplyBy2.andThen(add3);
      System.out.println(multiplyAndAdd.apply(5)); // 13
      // compose: 先执行参数函数,再执行当前函数
      Function<Integer, Integer> addAndMultiply = multiplyBy2.compose(add3);
        System.out.println(addAndMultiply.apply(5)); // 16
        // Predicate组合
        Predicate<Integer> isEven = x -> x % 2 == 0;
          Predicate<Integer> isGreaterThan10 = x -> x > 10;
            Predicate<Integer> isEvenAndGreaterThan10 = isEven.and(isGreaterThan10);
              System.out.println(isEvenAndGreaterThan10.test(12)); // true
              System.out.println(isEvenAndGreaterThan10.test(8));  // false
              // Consumer组合
              Consumer<String> print = System.out::println;
                Consumer<String> printTwice = print.andThen(print);
                  printTwice.accept("Hello");
                  }

实际应用案例

数据处理管道

定义 Person 类

public class Person {
private String name;
private int age;
private double salary;
public Person(String name, int age, double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
// getters
public String getName() { return name; }
public int getAge() { return age; }
public double getSalary() { return salary; }
}

测试程序

public static void testPipeline() {
List<Person> people = Arrays.asList(
  new Person("Alice", 25, 50000),
  new Person("Bob", 30, 60000),
  new Person("Charlie", 35, 70000),
  new Person("Diana", 28, 55000)
  );
  // 复杂的数据处理管道
  Map<String, Double> result = people.stream()
    // 过滤年龄
    .filter(p -> p.getAge() > 25)
    // 按薪资排序
    .sorted(Comparator.comparing(Person::getSalary))
    // 分组求平均薪资
    .collect(Collectors.groupingBy(
    p -> p.getAge() > 30 ? "Senior" : "Junior",
    Collectors.averagingDouble(Person::getSalary)
    ));
    System.out.println(result);
    }

异步编程

import java.util.concurrent.*;
import java.util.function.*;
public class AsyncProgramming {
public static void main(String[] args) throws Exception {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
  try {
  Thread.sleep(1000);
  return "Hello";
  } catch (InterruptedException e) {
  throw new IllegalStateException(e);
  }
  });
  CompletableFuture<String> result = future
    .thenApply(String::toUpperCase)
    .thenCompose(s -> CompletableFuture.supplyAsync(() -> s + " World"))
    .exceptionally(ex -> "Error: " + ex.getMessage());
    System.out.println(result.get()); // HELLO World
    }
    }

常见陷阱

// 在Lambda中修改外部变量
public static void modifyingExternalVariable() {
int[] counter = {0};
List<String> items = Arrays.asList("A", "B", "C");
  // 不好的做法:修改外部变量
  items.forEach(item -> counter[0]++);
  System.out.println(counter[0]);
  // 好的做法:使用归约
  long count = items.stream().count();
  System.out.println(count);
  }
  //过度使用链式操作
  public static void avoidOverChaining() {
  List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    // 不好的:过度链式操作,难以调试
    int result = numbers.stream()
    .filter(n -> n > 2)
    .map(n -> n * 2)
    .sorted()
    .distinct()
    .reduce(0, Integer::sum);
    System.out.println(result);
    // 好的:分步骤,清晰可读
    List<Integer> filtered = numbers.stream()
      .filter(n -> n > 2)
      .collect(Collectors.toList());
      List<Integer> doubled = filtered.stream()
        .map(n -> n * 2)
        .collect(Collectors.toList());
        int sum = doubled.stream()
        .reduce(0, Integer::sum);
        System.out.println(sum);
        }

总结

Java函数式编程的核心要点:

  1. 函数式接口:只有一个抽象方法的接口
  2. Lambda表达式:简洁的函数表示法
  3. 方法引用:更简洁的Lambda写法
  4. Stream API:强大的数据处理工具
  5. Optional:优雅的空值处理
  6. 函数组合:构建复杂操作

函数式编程使代码更简洁、可读性更强,并且更容易进行并行处理。但需要注意合理使用,避免过度复杂化。

完整代码

函数式接口 MyFunction.java

package function;
@FunctionalInterface
public interface MyFunction {
int apply(int a, int b);
//可以有默认方法
default void printResult(int result) {
System.out.println("MyFunction printResult 结果: " + result);
}
//可以有静态方法
static MyFunction add() {
return (a, b) -> a + b;
}
}

Person.java

package function;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
class Person {
private String name;
private int age;
private double salary;
}

主测试类 Main.java

package function;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* 函数式编程测试
*/
public class Main {
public static void main(String[] args) throws Exception {
// 函数式接口
doSomething(MyFunction.add(), 2, 3);
// Lambda函数接口
testLambdaFunction();
// 常用函数式接口
testCommFunction();
// 方法引用
testMethodRefFunction();
// stream 基本操作
testStream();
// 高级Stream操作
testStream2();
// optional
testOptional();
// 函数组合
testComposeFunction();
// 数据处理管道
testPipeline();
// 异步编程
testAsync();
// 在Lambda中修改外部变量
modifyingExternalVariable();
//过度使用链式操作
avoidOverChaining();
}
private static void testMethodRefFunction() {
List<String> names = Arrays.asList("Charlie", "Alice", "Bob", "\n");
  // 1. 静态方法引用
  names.forEach(System.out::println);
  // 2. 实例方法引用
  String prefix = "Hello, ";
  names.stream().map(prefix::concat).forEach(System.out::println);
  // 3. 特定类型的任意对象方法引用
  names.sort(String::compareToIgnoreCase);
  // 4. 构造方法引用
  names.stream()
  .map(String::new)
  .forEach(System.out::println);
  // 自定义方法用于方法引用
  System.out.println("\n过滤偶数:" + Stream.of(9, 5, 6, 3, 4, 2, 1, 8, 7).filter(Main::isEven).collect(Collectors.toList()));
  }
  public static boolean isEven(int number) {
  return number % 2 == 0;
  }
  private static void doSomething(MyFunction func, int a, int b) {
  int res = func.apply(a, b);
  func.printResult(res);
  }
  private static void testLambdaFunction() {
  Runnable runnable = () -> System.out.println("-1- runnable: Hello");
  Thread t = new Thread(runnable);
  t.start();
  Comparator<Integer> comparator = (a, b) -> a - b;
    System.out.println("-2- comparator 排序:" + Stream.of(9, 5, 6, 3, 4, 2, 1, 8, 7).sorted(comparator).collect(Collectors.toList()));
    MyFunction add = (a, b) -> a + b;
    MyFunction multiply = (a, b) -> a * b;
    System.out.println("-3- add.apply(2,3): " + add.apply(2, 3));
    System.out.println("-4- multiply.apply(2,3): " + multiply.apply(2, 3));
    }
    private static void testCommFunction() {
    // Predicate<T> - 接受一个参数,返回boolean
    Predicate<String> isLong = s -> s.length() > 5;
      System.out.println(isLong.test("Hello")); // false
      // Function<T, R> - 接受一个参数,返回结果
        Function<String, Integer> stringLength = String::length;
          System.out.println(stringLength.apply("Hello")); // 5
          // Consumer<T> - 接受一个参数,无返回值
          Consumer<String> printer = System.out::println;
            printer.accept("Hello World");
            // Supplier<T> - 无参数,返回一个结果
            Supplier<Double> randomSupplier = Math::random;
              System.out.println(randomSupplier.get());
              // UnaryOperator<T> - 接受一个参数,返回同类型结果
              UnaryOperator<String> toUpper = String::toUpperCase;
                System.out.println(toUpper.apply("hello")); // HELLO
                // BinaryOperator<T> - 接受两个同类型参数,返回同类型结果
                BinaryOperator<Integer> sum = Integer::sum;
                  System.out.println(sum.apply(5, 3)); // 8
                  }
                  public static void testStream() {
                  List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
                    // 过滤和映射
                    List<Integer> result = numbers.stream()
                      .filter(n -> n % 2 == 0)        // 中间操作:过滤偶数
                      .map(n -> n * n)               // 中间操作:平方
                      .collect(Collectors.toList()); // 终端操作:收集结果
                      System.out.println(result); // [4, 16, 36, 64, 100]
                      // 更多操作
                      numbers.stream()
                      .distinct()                    // 去重
                      .sorted()                      // 排序
                      .limit(5)                      // 限制数量
                      .skip(2)                       // 跳过前n个
                      .forEach(System.out::println); // 遍历
                      }
                      public static void testStream2() {
                      List<String> words = Arrays.asList("Hello", "World", "Java", "Stream");
                        // 归约操作
                        Optional<Integer> totalLength = words.stream()
                          .map(String::length)
                          .reduce(Integer::sum);
                          System.out.println("总长度: " + totalLength.orElse(0));
                          // 分组
                          Map<Integer, List<String>> lengthMap = words.stream()
                            .collect(Collectors.groupingBy(String::length));
                            System.out.println("按长度分组: " + lengthMap);
                            // 分区
                            Map<Boolean, List<String>> partition = words.stream()
                              .collect(Collectors.partitioningBy(s -> s.length() > 4));
                              System.out.println("按长度分区: " + partition);
                              // 连接字符串
                              String joined = words.stream()
                              .collect(Collectors.joining(", ", "[", "]"));
                              System.out.println("连接结果: " + joined);
                              }
                              public static void testOptional() {
                              // 创建Optional
                              Optional<String> empty = Optional.empty();
                                Optional<String> nonEmpty = Optional.of("Hello");
                                  Optional<String> nullable = Optional.ofNullable(null);
                                    // 使用Optional
                                    String result = nullable
                                    .map(String::toUpperCase)          // 如果值存在则转换
                                    .orElse("Default Value");         // 如果为空返回默认值
                                    System.out.println(result); // Default Value
                                    nullable.ifPresent(value -> System.out.println("值存在: " + value));
                                    // 链式操作
                                    Optional<String> finalResult = Optional.of(nonEmpty
                                      .filter(s -> s.length() > 3)
                                      .map(String::toUpperCase)
                                      .orElse("FALLBACK"));
                                      System.out.println(finalResult.get()); // HELLO
                                      }
                                      public static void testComposeFunction() {
                                      // 函数组合
                                      Function<Integer, Integer> multiplyBy2 = x -> x * 2;
                                        Function<Integer, Integer> add3 = x -> x + 3;
                                          // andThen: 先执行当前函数,再执行参数函数
                                          Function<Integer, Integer> multiplyAndAdd = multiplyBy2.andThen(add3);
                                            System.out.println(multiplyAndAdd.apply(5)); // 13
                                            // compose: 先执行参数函数,再执行当前函数
                                            Function<Integer, Integer> addAndMultiply = multiplyBy2.compose(add3);
                                              System.out.println(addAndMultiply.apply(5)); // 16
                                              // Predicate组合
                                              Predicate<Integer> isEven = x -> x % 2 == 0;
                                                Predicate<Integer> isGreaterThan10 = x -> x > 10;
                                                  Predicate<Integer> isEvenAndGreaterThan10 = isEven.and(isGreaterThan10);
                                                    System.out.println(isEvenAndGreaterThan10.test(12)); // true
                                                    System.out.println(isEvenAndGreaterThan10.test(8));  // false
                                                    // Consumer组合
                                                    Consumer<String> print = System.out::println;
                                                      Consumer<String> printTwice = print.andThen(print);
                                                        printTwice.accept("Hello");
                                                        }
                                                        public static void testPipeline() {
                                                        List<Person> people = Arrays.asList(
                                                          new Person("Alice", 25, 50000),
                                                          new Person("Bob", 30, 60000),
                                                          new Person("Charlie", 35, 70000),
                                                          new Person("Diana", 28, 55000)
                                                          );
                                                          // 复杂的数据处理管道
                                                          Map<String, Double> result = people.stream()
                                                            // 过滤年龄
                                                            .filter(p -> p.getAge() > 25)
                                                            // 按薪资排序
                                                            .sorted(Comparator.comparing(Person::getSalary))
                                                            // 分组求平均薪资
                                                            .collect(Collectors.groupingBy(
                                                            p -> p.getAge() > 30 ? "Senior" : "Junior",
                                                            Collectors.averagingDouble(Person::getSalary)
                                                            ));
                                                            System.out.println(result);
                                                            }
                                                            public static void testAsync() throws Exception {
                                                            CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
                                                              try {
                                                              Thread.sleep(1000);
                                                              return "Hello";
                                                              } catch (InterruptedException e) {
                                                              throw new IllegalStateException(e);
                                                              }
                                                              });
                                                              CompletableFuture<String> result = future
                                                                .thenApply(String::toUpperCase)
                                                                .thenCompose(s -> CompletableFuture.supplyAsync(() -> s + " World"))
                                                                .exceptionally(ex -> "Error: " + ex.getMessage());
                                                                // HELLO World
                                                                System.out.println(result.get());
                                                                }
                                                                public static void modifyingExternalVariable() {
                                                                int[] counter = {0};
                                                                List<String> items = Arrays.asList("A", "B", "C");
                                                                  // 不好的做法:修改外部变量
                                                                  items.forEach(item -> counter[0]++);
                                                                  System.out.println(counter[0]);
                                                                  // 好的做法:使用归约
                                                                  long count = items.stream().count();
                                                                  System.out.println(count);
                                                                  }
                                                                  public static void avoidOverChaining() {
                                                                  List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
                                                                    // 不好的:过度链式操作,难以调试
                                                                    int result = numbers.stream()
                                                                    .filter(n -> n > 2)
                                                                    .map(n -> n * 2)
                                                                    .sorted()
                                                                    .distinct()
                                                                    .reduce(0, Integer::sum);
                                                                    System.out.println(result);
                                                                    // 好的:分步骤,清晰可读
                                                                    List<Integer> filtered = numbers.stream()
                                                                      .filter(n -> n > 2)
                                                                      .collect(Collectors.toList());
                                                                      List<Integer> doubled = filtered.stream()
                                                                        .map(n -> n * 2)
                                                                        .collect(Collectors.toList());
                                                                        int sum = doubled.stream()
                                                                        .reduce(0, Integer::sum);
                                                                        System.out.println(sum);
                                                                        }
                                                                        }