Java Function接口

Java Function接口,用户希望实现 java.util.function.Function 接口,以便将输入参数转换为输出值,可以提供一个实现 R apply(T t) 方法的 lambda 表达式。Function 接口包含的单一抽象方法为 apply,它可以将 T 类型的泛型输入参数转换为 R 类型的泛型输出值。

Java Function接口 问题描述

用户希望实现 java.util.function.Function 接口,以便将输入参数转换为输出值。

Java Function接口 解决方案

提供一个实现 R apply(T t) 方法的 lambda 表达式。

Java Function接口 具体实例

Function 接口包含的单一抽象方法为 apply,它可以将 T 类型的泛型输入参数转换为 R 类型的泛型输出值。例 2-12 列出了 Function 接口定义的所有方法。

例 2-12 Function 接口定义的方法

default <V> Function<T,V> andThen(Function<? super R,? extends V> after)
            R             apply(T t)
default <V> Function<V,R> compose(Function<? super V,? extends T> before)
static  <T> Function<T,T> identity()

Function 最常见的用法是作为 Stream.map 方法的一个参数。例如,为了将 string 转换为整数,可以在每个实例上调用 length 方法,如例 2-13 所示。

例 2-13 将字符串映射到它们的长度

List<String> names = Arrays.asList("Mal", "Wash", "Kaylee", "Inara",
        "Zoë", "Jayne", "Simon", "River", "Shepherd Book");

List<Integer> nameLengths = names.stream()
        .map(new Function<String, Integer>() { ➊
            @Override
            public Integer apply(String s) {
                return s.length();
            }
        })
        .collect(Collectors.toList());

nameLengths = names.stream()
        .map(s -> s.length())                  ➋
        .collect(Collectors.toList());

nameLengths = names.stream()
        .map(String::length)                   ➌
        .collect(Collectors.toList());

System.out.printf("nameLengths = %s%n", nameLengths);
// nameLengths == [3, 4, 6, 5, 3, 5, 5, 5, 13]

❶ 匿名内部类
❷ lambda 表达式
❸ 方法引用
表 2-3 列出了输入和输出泛型类型的所有基本变体。
表2-3:其他Function接口

接口 单一抽象方法
IntFunction R apply(int value)
DoubleFunction R apply(double value)
LongFunction R apply(long value)
ToIntFunction int applyAsInt(T value)
ToDoubleFunction double applyAsDouble(T value)
ToLongFunction long applyAsLong(T value)
DoubleToIntFunction int applyAsInt(double value)
DoubleToLongFunction long applyAsLong(double value)
IntToDoubleFunction double applyAsDouble(int value)
IntToLongFunction long applyAsLong(int value)
LongToDoubleFunction double applyAsDouble(long value)
LongToIntFunction int applyAsInt(long value)
BiFunction R apply(T t, U u)

在例 2-13 中,由于 map 方法返回的是基本数据类型 int,该方法的参数可能是 ToIntFunctionStream.mapToInt 方法传入 ToIntFunction 作为参数,mapToDoublemapToLong 方法与之类似。
mapToIntmapToDoublemapToLong 的返回类型分别为 IntStreamDoubleStreamLongStream
那么,如果输入参数和返回类型相同呢? java.util.function 包为此定义了 UnaryOperator 接口,以及相应的 IntUnaryOperatorDoubleUnaryOperatorLongUnaryOperator 接口,三者的输入和输出参数分别为 intdoublelongUnaryOperator 的一种应用是 StringBuilderreverse 方法,因为输入类型和输出类型均为字符串。
BiFunction 接口定义了两个泛型输入类型和一个泛型输出类型,三者应为不同的类型。如果三者相同,可以使用 java.util.function 包定义的 BinaryOperator 接口。Math.max 就是一种二元运算符,其输入和输出为 intdoublefloatlong 型数据。相应地,java.util.function 包也定义了 IntBinaryOperatorDoubleBinaryOperatorLongBinaryOperator 接口。3
3有关 Java 标准库中 BinaryOperator 用法的详细讨论,请参见范例利用reduce方法实现归约操作
表 2-4 列出了 BiFunction 接口的所有基本变体。
表2-4:其他BiFunction接口

接口 单一抽象方法
ToIntBiFunction int applyAsInt(T t, U u)
ToDoubleBiFunction double applyAsDouble(T t, U u)
ToLongBiFunction long applyAsLong(T t, U u)

尽管 Function 主要用于各种 Stream.map 方法,但这些方法也可能出现在其他上下文中,举例如下。
Map.computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)
  如果指定的键没有值,使用所提供的 Function 计算一个值并将其添加到 Map
Comparator.comparing(Function<? super T,? extends U> keyExtractor)
  comparing 方法生成一个 Comparator,使用给定 Function 生成的键对集合进行排序。相关讨论请参见范例 利用比较器实现排序
Comparator.thenComparing(Function<? super T,? extends U> keyExtractor)
  thenComparing 是一种实例方法,也可以用于排序。如果集合的首次排序返回相同的值,则使用另一种机制进行排序。
此外,Function 还广泛用于分组和下游收集器(downstream collector)的 Collectors 工具类中。
有关 andThencompose 方法的讨论请参见范例闭包复合identity 方法实际上是一种简单的 lambda 表达式(e -> e),范例 将线性集合添加到映射 将介绍其中一种应用。

赞(2)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

Java 实例