# 一.基本介绍

# 1.什么是函数式接口?

在 Java 中,函数接口通常指的是函数式接口(Functional Interface)。函数式接口是 Java 8 引入的一个特性,它是一个只包含一个抽象方法的接口。函数式接口的主要目的是支持 Lambda 表达式和方法引用,使得函数式编程更加容易和方便。

# 2.函数式接口的定义?

函数式接口有一个特殊的注解 @FunctionalInterface,用来标识该接口是一个函数式接口。如果一个接口使用了 @FunctionalInterface 注解,并且不满足函数式接口的条件(拥有多个抽象方法),编译器将会报错。

以下是一个简单的函数式接口示例:

@FunctionalInterface
interface MyFunction {
    int apply(int a, int b);
}
1
2
3
4

在上面的示例中,MyFunction 是一个函数式接口,因为它只有一个抽象方法 apply

你可以使用 Lambda 表达式或方法引用来实现函数式接口的实例,例如:

MyFunction add = (a, b) -> a + b;
MyFunction subtract = (a, b) -> a - b;
1
2

# 3.常用的函数式接口

以下是一些常用的函数式接口:

  1. Consumer(java.util.function.Consumer<T>):接受一个输入参数,但不返回结果,通常用于执行某些操作。
  2. Supplier (java.util.function.Supplier<T>):表示一个供应商,它不接受参数,但返回一个值。在函数式编程中,常用于延迟计算或提供初始值。
  3. Function (java.util.function.Function<T, R>):表示一个函数,它接受一个参数类型为 T 的对象,然后返回一个类型为 R 的结果对象。
  4. Predicate (java.util.function.Predicate<T>):表示一个断言,它接受一个参数类型为 T 的对象,返回一个布尔值,用于判断对象是否满足某个条件。
  5. UnaryOperator (java.util.function.UnaryOperator<T>):是一个特殊的 Function,输入和输出类型都是相同的。用于表示只接受一个参数并返回相同类型结果的操作。
  6. BinaryOperator (java.util.function.BinaryOperator<T>):是一个特殊的 Function,输入和输出类型都是相同的。用于表示接受两个参数并返回一个相同类型结果的操作。
  7. BiFunction (java.util.function.BiFunction<T, U, R>):与 Function 类似,但接受两个参数类型分别为 TU 的对象,然后返回一个类型为 R 的结果对象。
  8. Consumer 接口的变种: 除了常规的 Consumer,还有 IntConsumerLongConsumerDoubleConsumer 分别用于处理整数、长整数和双精度浮点数。

这些函数式接口可以通过 Java 8 中的 java.util.function 包来使用,它们在函数式编程和 Lambda 表达式的应用中非常有用,可以让代码更加简洁和易于理解。

# 二.Consumer

# 1.Consumer 介绍

Consumer 可以在函数式编程中的很多场景中使用,例如遍历集合并执行某种操作,执行异步任务的回调等。

是的,除了 Consumer,Java 8 引入了一系列函数式接口,用于支持不同类型的函数式操作。

在 Java 8 中,Consumer 是一个函数式接口,它定义了一个接受一个参数并且不返回任何结果的操作。它在函数式编程中常用于表示一个可以对传入的参数执行某种操作的函数。

Consumer 接口中的抽象方法是 accept(T t),其中 T 是输入参数的类型。下面是 Consumer 接口的定义:

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);

    // 其他默认方法和静态方法省略
}
1
2
3
4
5
6

函数式接口的注解 @FunctionalInterface 表示该接口是一个函数式接口,即只包含一个抽象方法。这样的接口可以使用 Lambda 表达式来实例化。

Consumer 接口有一个抽象方法 accept(T t),该方法接受一个参数类型为 T 的对象,并对该对象进行操作,但不返回任何结果。

"Consumer" 是 Java 中的一个函数式接口,它属于 Java.util.function 包。函数式接口是指只包含一个抽象方法的接口。Consumer 接口表示一个接受单个输入参数并且不返回结果的操作。它通常用于接受某个对象,并对其执行一些操作,比如修改对象的状态或者打印信息。

# 2.Consumer 使用

下面是 Consumer 的简单示例:

import java.util.function.Consumer;

public class ConsumerExample {
    public static void main(String[] args) {
        // 使用 Consumer 打印字符串
        Consumer<String> printConsumer = str -> System.out.println(str);
        printConsumer.accept("Hello, world!");

        // 使用 Consumer 修改集合中的元素
        List<String> names = new ArrayList<>();
        names.add("Alice");
        names.add("Bob");
        names.add("Charlie");

        Consumer<List<String>> modifyConsumer = list -> {
            for (int i = 0; i < list.size(); i++) {
                list.set(i, list.get(i).toUpperCase());
            }
        };

        modifyConsumer.accept(names);
        System.out.println(names); // 输出: [ALICE, BOB, CHARLIE]
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

在上面的示例中,我们创建了两个不同的 Consumer 实例,一个用于打印字符串,另一个用于将集合中的元素转换为大写。accept 方法负责执行相应的操作。

# 3.Consumer 参数传递

import java.util.Arrays;
import java.util.List;

public class ConsumerExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

        // 使用 Consumer 接口打印每个名字
        names.forEach(name -> {
            Consumer<String> printName = s -> System.out.println(s);
            printName.accept(name);
        });
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

上述代码使用了 forEach 方法,将 Consumer 接口作为参数传递,以打印每个名字。Lambda 表达式使得代码更为简洁和易读。

# 三.Supplier

# 1.什么是 Supplier?

"Supplier" 是 Java 编程语言中的一个函数式接口(Functional Interface)。在 Java 8 中引入了函数式编程的特性,为了支持这一特性,引入了一些新的函数式接口,其中 Supplier 就是其中之一。

在函数式编程中,函数是一等公民,这意味着可以将函数作为参数传递给其他函数,也可以从函数中返回函数。Supplier 是一个代表生产(提供)数据的函数式接口。它不接受任何参数,但返回一个值。它的声明如下:

@FunctionalInterface
public interface Supplier<T> {
    T get();
}
1
2
3
4

这里,T 是返回值的类型。get 方法不接受任何参数,但返回类型为 T 的值。

# 2.获取随机数

使用 Supplier 的一个例子是延迟计算,其中某个值只有在需要的时候才会被计算。例如:

import java.util.function.Supplier;

public class SupplierExample {
    public static void main(String[] args) {
        // 使用 Supplier 创建一个延迟计算的值
        Supplier<Double> randomSupplier = () -> Math.random();

        // 获取值
        double randomValue = randomSupplier.get();
        System.out.println("Random value: " + randomValue);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

在上面的例子中,randomSupplier 是一个 Supplier,它在调用 get 方法时返回一个随机的 double 值。这样,我们可以在需要随机值的地方调用 get 方法。

函数式接口的引入使得在 Java 中更容易进行函数式编程,带来了更简洁、灵活的代码编写方式。

# 3.安全的 DateFormat

创建 ThreadLocal 对象

//创建线程安全的DateFormat
public final static ThreadLocal<DateFormat> formatter = withInitial(() -> new SimpleDateFormat("dd-MMM-yyyy"));
1
2

源码:

//可以看到参数是Supplier,表示不要参数,返回一个值
public static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier) {
    return new SuppliedThreadLocal<>(supplier);
}
1
2
3
4
上次更新: 10/29/2024, 10:27:50 AM