在Java8支持Lambda表达式以后,为了满足Lambda表达式的一些典型使用场景,JDK为我们提供了大量常用的函数式接口。它们主要在 java.util.function
包中,下面简单介绍几个其中的接口及其使用示例。
Supplier接口
Supplier接口是对象实例的提供者,定义了一个名叫get的抽象方法,它没有任何入参,并返回一个泛型T对象。package java.util.function;
@FunctionalInterface
public interface Supplier<T> {
T get();
}
可以看看下面的例子:Supplier<String> stringCallable = () -> new String("");
这里的lambda
声明了一个Supplier
的实例。
它提供了一个get
方法,来获取里面得到数值。String data = stringCallable.get();
Consumer接口
Consumer
接口是一个类似消费者的接口,定义了一个名叫accept
的抽象方法,它的入参是一个泛型T对象,没有任何返回(void),主要源码如下:package java.util.function;
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
可以看看下面的例子:final Consumer<String> stringConsumer = (String data) -> {};
Predicate接口
Predicate
接口是判断是与否的接口,定义了一个名叫test
的抽象方法,它的入参是一个泛型T对象,并返回一个boolean
类型,主要源码如下:package java.util.function;
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
可以看看下面的例子:final Predicate<String> stringFilter = (String data) -> data.isEmpty();
Function接口
Function
接口是对实例进行处理转换的接口,定义了一个名叫apply
的抽象方法,它的入参是一个泛型T对象,并返回一个泛型R对象,主要源码如下:package java.util.function;
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
可以看看下面的例子:final Function<String, Integer> stringIntegerFunction = (String data) -> new Integer(1);
BiFunction接口
Function
接口的入参只有一个泛型对象,JDK还为我们提供了两个泛型对象入参的接口:BiFunction
接口,主要源码如下:package java.util.function;
@FunctionalInterface
public interface BiFunction<T, U, R> {
R apply(T t, U u);
}
可以看看下面的例子:final BiFunction<String, Integer, Double> stringIntegerDoubleBiFunction = (String data, Integer item) -> Double.parseDouble(item.toString());
基本数据类型
以上介绍的几个常用的函数式接口入参和返回,都是泛型对象的,也就是必须为引用类型。当我们传入或获取的是基本数据类型时,将会发生自动装箱和自动拆箱,带来不必要的性能损耗。
JDK为我们提供相应的函数式接口,如LongSupplier
接口,定义了一个名叫getAsLong的抽象方法,签名是() -> long
。
Supplier相关的接口
接口名称 | 方法名称 | 方法签名 |
---|---|---|
Supplier | get | () -> T |
BooleanSupplier | getAsBoolean | () -> boolean |
DoubleSupplier | getAsDouble | () -> double |
IntSupplier | getAsInt | () -> int |
LongSupplier | getAsLong | () -> long |
Consumer相关的接口
接口名称 | 方法名称 | 方法签名 |
---|---|---|
Consumer | accept | (T) -> void |
DoubleConsumer | accept | (double) -> void |
IntConsumer | accept | (int) -> void |
LongConsumer | accept | (long) -> void |
ObjDoubleConsumer | accept | (T, double) -> void |
ObjIntConsumer | accept | (T, int) -> void |
ObjLongConsumer | accept | (T, long) -> void |
Predicate相关的接口
接口名称 | 方法名称 | 方法签名 |
---|---|---|
Predicate | test | (T) -> boolean |
BiPredicate | test | (T, U) -> boolean |
DoublePredicate | test | (double) -> boolean |
IntPredicate | test | (int) -> boolean |
LongPredicate | test | (long) -> boolean |
Function相关的接口
接口名称 | 方法名称 | 方法签名 |
---|---|---|
Function | apply | (T) -> R |
BiFunction | apply | (T, U) -> R |
DoubleFunction | apply | (double) -> R |
DoubleToIntFunction | applyAsInt | (double) -> int |
DoubleToLongFunction | applyAsLong | (double) -> long |
IntFunction | apply | (int) -> R |
IntToDoubleFunction | applyAsDouble | (int) -> double |
IntToLongFunction | applyAsLong | (int) -> long |
LongFunction | apply | (long) -> R |
LongToDoubleFunction | applyAsDouble | (long) -> double |
LongToIntFunction | applyAsInt | (long) -> int |
ToDoubleFunction | applyAsDouble | (T) -> double |
ToDoubleBiFunction | applyAsDouble | (T, U) -> double |
ToIntFunction | applyAsInt | (T) -> int |
ToIntBiFunction | applyAsInt | (T, U) -> int |
ToLongFunction | applyAsLong | (T) -> long |
ToLongBiFunction | applyAsLong | (T, U) -> long |
函数式编程
函数式编程就是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用。
Java8内置了一些常用的方法接口FunctionalInterface
这种接口只定义了一个抽象方法,并且用@FunctionalInterface
注解标记,如Predicate,Consumer,Function,Supplier,Comparator等等,这些都属于java.util.function
包中@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
// 省略不贴了
在使用时,传入类名::实例方法名
实现的效果是等价的