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
,该方法的参数可能是 ToIntFunction
。Stream.mapToInt
方法传入 ToIntFunction
作为参数,mapToDouble
和 mapToLong
方法与之类似。
mapToInt
、mapToDouble
与 mapToLong
的返回类型分别为 IntStream
、DoubleStream
和 LongStream
。
那么,如果输入参数和返回类型相同呢? java.util.function
包为此定义了 UnaryOperator
接口,以及相应的 IntUnaryOperator
、DoubleUnaryOperator
和 LongUnaryOperator
接口,三者的输入和输出参数分别为 int
、double
和 long
。UnaryOperator
的一种应用是 StringBuilder
的 reverse
方法,因为输入类型和输出类型均为字符串。
BiFunction
接口定义了两个泛型输入类型和一个泛型输出类型,三者应为不同的类型。如果三者相同,可以使用 java.util.function
包定义的 BinaryOperator
接口。Math.max
就是一种二元运算符,其输入和输出为 int
、double
、float
或 long
型数据。相应地,java.util.function
包也定义了 IntBinaryOperator
、DoubleBinaryOperator
与 LongBinaryOperator
接口。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
工具类中。
有关 andThen
和 compose
方法的讨论请参见范例闭包复合。identity
方法实际上是一种简单的 lambda 表达式(e -> e
),范例 将线性集合添加到映射 将介绍其中一种应用。