后端 · 2025年 1月 6日 0

java函数式编程和函数式接口

上述的函数式接口都归属于 Java 的 函数式编程(Functional Programming)函数式接口(Functional Interfaces) 部分。具体来说,它们位于 Java 8 引入的 java.util.function 包中,旨在提供一组标准的函数式接口,以便在函数式编程风格中使用。

函数式编程和函数式接口

函数式编程

函数式编程是一种编程范式,强调使用数学函数的概念来构建计算机程序。在函数式编程中,函数是一等公民,可以作为参数传递给其他函数,也可以作为函数的返回值。Java 8 引入了对函数式编程的支持,包括 lambda 表达式、方法引用和函数式接口。

留空

函数式接口

函数式接口是 Java 中的一种特殊接口,它只有一个抽象方法(即 SAM,Single Abstract Method)。Java 8 引入了 @FunctionalInterface 注解,用于标记这样的接口。函数式接口可以被 lambda 表达式隐式地实例化。

java.util.function

java.util.function 包提供了许多常用的函数式接口,这些接口可以用于各种函数式编程场景。以下是一些关键的包和接口:

  • java.util.function
  • 包含了许多预定义的函数式接口,如 FunctionBiFunctionConsumerBiConsumerSupplierPredicateBiPredicateUnaryOperatorBinaryOperator
  • 这些接口的设计目的是为了简化 lambda 表达式的使用,使代码更加简洁和易读。

常见的函数式接口及其用途

1. Function<T, R>

  • 用途:接受一个参数并返回一个结果。
  • 主要方法R apply(T t)
  • 示例
  Function<String, Integer> stringToLength = String::length;
  int length = stringToLength.apply("Hello"); // 结果是 5

2. BiFunction<T, U, R>

  • 用途:接受两个参数并返回一个结果。
  • 主要方法R apply(T t, U u)
  • 示例
  BiFunction<Integer, Integer, Integer> adder = (a, b) -> a + b;
  int result = adder.apply(3, 4); // 结果是 7

3. Consumer<T>

  • 用途:接受一个参数,不返回任何结果。
  • 主要方法void accept(T t)
  • 示例
  Consumer<String> printString = System.out::println;
  printString.accept("Hello"); // 输出: Hello

4. BiConsumer<T, U>

  • 用途:接受两个参数,不返回任何结果。
  • 主要方法void accept(T t, U u)
  • 示例
  BiConsumer<String, Integer> printMessage = (message, count) -> {
      for (int i = 0; i < count; i++) {
          System.out.println(message);
      }
  };
  printMessage.accept("Hello", 3); // 输出: Hello
                                   //       Hello
                                   //       Hello

5. Supplier<T>

  • 用途:不接受任何参数,返回一个结果。
  • 主要方法T get()
  • 示例
  Supplier<Double> randomSupplier = Math::random;
  double randomValue = randomSupplier.get(); // 返回一个随机数

6. Predicate<T>

  • 用途:接受一个参数并返回一个布尔值。
  • 主要方法boolean test(T t)
  • 示例
  Predicate<String> isEmpty = String::isEmpty;
  boolean result = isEmpty.test(""); // 结果是 true

7. BiPredicate<T, U>

  • 用途:接受两个参数并返回一个布尔值。
  • 主要方法boolean test(T t, U u)
  • 示例
  BiPredicate<Integer, Integer> isEqual = (a, b) -> a.equals(b);
  boolean result = isEqual.test(3, 3); // 结果是 true

8. UnaryOperator<T>

  • 用途:接受一个参数并返回一个相同类型的参数。
  • 主要方法T apply(T t)
  • 示例
  UnaryOperator<Integer> increment = x -> x + 1;
  int result = increment.apply(5); // 结果是 6

9. BinaryOperator<T>

  • 用途:接受两个相同类型的参数并返回一个相同类型的参数。
  • 主要方法T apply(T t, T u)
  • 示例
  BinaryOperator<Integer> adder = (a, b) -> a + b;
  int result = adder.apply(3, 4); // 结果是 7

处理可变参数

对于可变参数(varargs),Java 标准函数式接口并不直接支持。你可以使用 Function 或自定义函数式接口来处理可变参数。

使用 Function<int[], Integer> 处理可变参数

import java.util.function.Function;

public class Calculator {
    public static int sum(int... numbers) {
        int total = 0;
        for (int number : numbers) {
            total += number;
        }
        return total;
    }
}

public class Main {
    public static void main(String[] args) {
        Function<int[], Integer> sumFunction = Calculator::sum;
        int result = sumFunction.apply(new int[]{1, 2, 3, 4, 5}); // 结果是 15
        System.out.println("Sum: " + result);
    }
}

自定义函数式接口处理可变参数

@FunctionalInterface
interface VarArgsFunction {
    int apply(int... numbers);
}

public class Calculator {
    public static int sum(int... numbers) {
        int total = 0;
        for (int number : numbers) {
            total += number;
        }
        return total;
    }
}

public class Main {
    public static void main(String[] args) {
        VarArgsFunction sumFunction = Calculator::sum;
        int result = sumFunction.apply(1, 2, 3, 4, 5); // 结果是 15
        System.out.println("Sum: " + result);
    }
}