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)以及专门处理原始类型的版本,以提高性能。

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

相关推荐
得物技术17 小时前
破解gh-ost变更导致MySQL表膨胀之谜|得物技术
数据库·后端·mysql
小桥风满袖18 小时前
极简三分钟ES6 - ES9中字符串扩展
前端·javascript
小码编匠18 小时前
WPF 中的高级交互通过右键拖动实现图像灵活缩放
后端·c#·.net
小Wang18 小时前
npm私有库创建(docker+verdaccio)
前端·docker·npm
用户730870117930818 小时前
Vue中集成文字转语音:使用Web Speech API实现功能
前端
李重楼18 小时前
前端性能优化之 HTTP/2 多路复用
前端·面试
Java水解18 小时前
【MySQL】从零开始学习MySQL:基础与安装指南
后端·mysql
yanessa_yu18 小时前
全屏滚动网站PC端自适应方案
前端
Java水解18 小时前
Scala深入面向对象:类、对象与伴生关系
后端·scala
LeeGe18 小时前
基于binlog的canal到redis的同步
后端