154. Java Lambda 表达式 - 总结 Java 中的四类函数式接口

154. Java Lambda 表达式 - 总结 Java 中的四类函数式接口

java.util.function 包是 Java 8 引入的一个核心包,它在 Java 编程中扮演着重要角色。所有在 Collections FrameworkStream API 中使用的 lambda 表达式都实现了该包中的某个接口。

尽管 java.util.function 包中包含了很多接口,但它们可以大致分为四大类。了解这四类接口将帮助您更高效地使用函数式编程。

1. 供应者(Suppliers)

供应者接口不接收任何参数,但会返回某个结果。通常用于生成某些值或提供某些数据。

  • Supplier<T> 是供应者接口的一个例子,它的定义如下:

    java 复制代码
    @FunctionalInterface
    public interface Supplier<T> {
        T get();
    }

    示例: 使用 Supplier 返回一个随机数:

    java 复制代码
    Supplier<Double> randomValue = () -> Math.random();
    System.out.println(randomValue.get());
2. 消费者(Consumers)

消费者接口接收一个参数并执行某种操作,但不返回任何结果。它通常用于对输入进行处理,如打印或修改数据。

  • Consumer<T> 是消费者接口的一个例子:

    java 复制代码
    @FunctionalInterface
    public interface Consumer<T> {
        void accept(T t);
    }

    示例: 使用 Consumer 打印一个字符串:

    java 复制代码
    Consumer<String> print = s -> System.out.println(s);
    print.accept("Hello, world!");
3. 谓词(Predicates)

谓词接口接收一个参数并返回一个 boolean 值。它常用于过滤、判断条件等操作。

  • Predicate<T> 是谓词接口的一个例子:

    java 复制代码
    @FunctionalInterface
    public interface Predicate<T> {
        boolean test(T t);
    }

    示例: 使用 Predicate 检查一个字符串是否为指定长度:

    java 复制代码
    Predicate<String> isLength3 = s -> s.length() == 3;
    System.out.println(isLength3.test("abc"));  // true
    System.out.println(isLength3.test("abcd")); // false
4. 函数(Functions)

函数接口接收一个参数并返回某种类型的结果。它常用于对数据进行转换。

  • Function<T, R> 是函数接口的一个例子:

    java 复制代码
    @FunctionalInterface
    public interface Function<T, R> {
        R apply(T t);
    }

    示例: 使用 Function 将字符串转换为其长度:

    java 复制代码
    Function<String, Integer> toLength = s -> s.length();
    System.out.println(toLength.apply("hello"));  // 5

具有两个参数的版本

除了上述四大类函数式接口之外,还有一些接口版本,它们接受两个参数而不是一个。常见的接口包括:

  • BiConsumer<T, U>:接收两个参数并执行操作,但不返回结果。
  • BiPredicate<T, U> :接收两个参数并返回 boolean 值。
  • BiFunction<T, U, R>:接收两个参数并返回某个结果。
示例:使用 BiFunction 计算两个整数的和
java 复制代码
BiFunction<Integer, Integer, Integer> add = (a, b) -> a + b;
System.out.println(add.apply(5, 3));  // 8

专门的版本:避免装箱和拆箱

为了提高性能,Java 提供了一些专门的接口,这些接口避免了装箱和拆箱操作。它们的命名通常与所接受的类型或返回的类型相关。

示例:专门的 IntPredicate 接口

IntPredicatePredicate 的专门版本,用于处理 int 类型:

java 复制代码
IntPredicate isPositive = i -> i > 0;
System.out.println(isPositive.test(5));  // true
System.out.println(isPositive.test(-1)); // false

类似地,Java还提供了以下专门接口:

  • IntFunction<R>LongFunction<R>DoubleFunction<R>:接收原始类型并返回某个类型的结果。
  • ToIntFunction<T>ToLongFunction<T>ToDoubleFunction<T>:接收一个对象并返回原始类型的结果。
示例:使用 ToIntFunction<T> 将字符串转换为其长度(返回 int
java 复制代码
ToIntFunction<String> stringLength = s -> s.length();
System.out.println(stringLength.applyAsInt("hello"));  // 5

对于类型相同的操作,使用 UnaryOperator<T>BinaryOperator<T>

如果您有两个相同类型的参数,UnaryOperator<T>BinaryOperator<T>Function<T, T>BiFunction<T, T, T> 的特例。

  • UnaryOperator<T>:表示接受并返回相同类型的函数,通常用于修改或处理单一类型的数据。

    示例: 使用 UnaryOperator 将字符串转换为大写:

    java 复制代码
    UnaryOperator<String> toUpperCase = s -> s.toUpperCase();
    System.out.println(toUpperCase.apply("hello"));  // HELLO
  • BinaryOperator<T>:表示接受并返回相同类型的两个参数,通常用于二元操作(如加法、乘法等)。

    示例: 使用 BinaryOperator 计算两个整数的和:

    java 复制代码
    BinaryOperator<Integer> add = (a, b) -> a + b;
    System.out.println(add.apply(5, 3));  // 8

总结

java.util.function 包包含了多种功能强大的接口,您可以根据需求选择合适的接口进行使用。总的来说,它们分为四类:

  • 供应者(Suppliers):不接收任何参数,返回一个值。
  • 消费者(Consumers):接收一个参数,不返回任何值。
  • 谓词(Predicates) :接收一个参数,返回 boolean 值。
  • 函数(Functions):接收一个参数,返回一个结果。

除此之外,Java 还提供了带两个参数的版本(如 BiConsumerBiPredicateBiFunction)以及专门处理原始类型的版本,以提高性能。

通过合理使用这些函数式接口,您能够编写更加简洁、易读且高效的代码,特别是在流操作和数据转换方面。

相关推荐
卑微前端在线挨打34 分钟前
2025数字马力一面面经(社)
前端
OpenTiny社区1 小时前
一文解读“Performance面板”前端性能优化工具基础用法!
前端·性能优化·opentiny
拾光拾趣录1 小时前
🔥FormData+Ajax组合拳,居然现在还用这种原始方式?💥
前端·面试
不会笑的卡哇伊1 小时前
新手必看!帮你踩坑h5的微信生态~
前端·javascript
bysking1 小时前
【28 - 记住上一个页面tab】实现一个记住用户上次点击的tab,上次搜索过的数据 bysking
前端·javascript
我是不会赢的1 小时前
使用 decimal 包解决 go float 浮点数运算失真
开发语言·后端·golang·浮点数
Dream耀1 小时前
跨域问题解析:从同源策略到JSONP与CORS
前端·javascript
前端布鲁伊1 小时前
【前端高频面试题】面试官: localhost 和 127.0.0.1有什么区别
前端
HANK1 小时前
Electron + Vue3 桌面应用开发实战指南
前端·vue.js