【发布时间】:2015-01-02 13:56:03
【问题描述】:
我正在寻找java.util.function 中所有接口的单一抽象方法 (SAM) 的参数和返回类型表。
【问题讨论】:
标签: java functional-programming functional-interface
我正在寻找java.util.function 中所有接口的单一抽象方法 (SAM) 的参数和返回类型表。
【问题讨论】:
标签: java functional-programming functional-interface
这是包中所有 43 个接口的表格,以及其他一些值得注意的接口。这种安排应该可以很容易地看到包中的命名模式。该表旨在用作 .java 类文件中的注释。在 eclipse(或任何其他可以解析 cmets 中的类名的 IDE)中打开该文件。您应该能够将鼠标悬停在名称上并查看它们的 javadocs。 ctrl-click 将打开接口源代码,如果你正确地attached the java source code。
(令人惊讶的是,这在 InteliJ 中似乎不起作用。如果我缺少某个设置,请告诉我。)
import java.util.function.Function; //Prevent "which package?" popups
import java.util.function.Predicate;
抽象方法声明“抛出异常”的接口,用 * 表示
/* Param\Return void boolean R
---- ------- -
void Runnable BooleanSupplier Supplier<R>
void AutoCloseable* Callable<R>*
T Consumer<T> Predicate<T> Function<T,R>
R UnaryOperator<R>
T, U BiConsumer<T,U> BiPredicate<T,U> BiFunction<T,U,R>
R, R BinaryOperator<R>
int IntConsumer IntPredicate IntFunction<R>
T, int ObjIntConsumer<T>
long LongConsumer LongPredicate LongFunction<R>
T, long ObjLongConsumer<T>
double DoubleConsumer DoublePredicate DoubleFunction<R>
T, double ObjDoubleConsumer<T>
Param\Return int long double
--- ---- ------
void IntSupplier LongSupplier DoubleSupplier
T ToIntFunction<T> ToLongFunction<T> ToDoubleFunction<T>
T,U ToIntBiFunction<T,U> ToLongBiFunction<T,U> ToDoubleBiFunction<T,U>
int IntUnaryOperator IntToLongFunction IntToDoubleFunction
int, int IntBinaryOperator
long LongToIntFunction LongUnaryOperator LongToDoubleFunction
long, long LongBinaryOperator
double DoubleToIntFunction DoubleToLongFunction DoubleUnaryOperator
double, double DoubleBinaryOperator */
一些使用示例:
// Lambda using Runnable
new Thread(() -> System.out.println(Thread.currentThread().getName())).start();
Optional<String> opt = Optional.of("Meh");
// Lambda using Predicate<? super String>;
opt = opt.filter( s->s.equalsIgnoreCase("meh") );
System.out.println(opt+" <-- opt");
// Lambda using Consumer<? super String>;
opt.ifPresent( s->System.out.println(s) );
// Lambda using Function<? super String, ? extends String>;
opt = opt.map(s->s+"!").map(s->s+"!");
System.out.println(opt+" <-- opt");
// Lambda using Supplier<? extends IllegalArgumentException>;
opt.orElseThrow( ()->new IllegalArgumentException("Should not be empty.") );
opt = Optional.empty();
opt.orElseThrow(
()->new IllegalArgumentException("Empty? Who said you could be empty?")
);
Thread-0
Optional[Meh] <-- opt
Meh
Optional[Meh!!] <-- opt
Exception in thread "main" java.lang.IllegalArgumentException:
Empty? Who said you could be empty?
at functionalinterfacestudy.AllLambdas.lambda$6(AllLambdas.java:110)
at functionalinterfacestudy.AllLambdas$$Lambda$7/1392838282.get(Unknown Source)
at java.util.Optional.orElseThrow(Unknown Source)
at functionalinterfacestudy.AllLambdas.main(AllLambdas.java:110)
另外,本书还提供了一些detailed tables的包。
而且,虽然它不是一张桌子,但阅读official package summery 总是好的。
JDK 实际上有 57 个使用 @FunctionalInterface annotation 的接口。以上未提及的包括:
import java.io.FileFilter; // Aren't name collisions fun?
import java.io.FilenameFilter;
import java.util.Comparator;
import java.util.logging.Filter;
/*
Interface Single Abstract Method
--------- ----------------------
KeyEventDispatcher: boolean dispatchKeyEvent(KeyEvent e);
KeyEventPostProcessor: boolean postProcessKeyEvent(KeyEvent e);
FileFilter: boolean accept(File pathname);
FilenameFilter: boolean accept(File dir, String name);
Thread.UncaughtExceptionHandler: void uncaughtException(Thread t, Throwable e);
DirectoryStream<T>.Filter<T>: boolean accept(T entry) throws IOException;
PathMatcher: boolean matches(Path path);
TemporalAdjuster: Temporal adjustInto(Temporal temporal);
TemporalQuery<R>: R queryFrom(TemporalAccessor temporal);
Comparator<T>: int compare(T o1, T o2);
Filter: public boolean isLoggable(LogRecord record);
PreferenceChangeListener: void preferenceChange(PreferenceChangeEvent evt);
*/
但是,JDK 有许多接口满足成为没有@FunctionalInterface 注释的功能接口的所有要求(例如AutoClosable)。缺少的注释不会阻止它们作为功能接口工作。它用于在接口违反功能接口的定义时强制编译器抛出错误。在某种程度上,承诺不会扩展您在实现接口时必须覆盖的抽象方法集(可以添加默认方法,因为它们总是有自己的实现)。这让我想知道:why it isn't @FunctionalInterface used on all the interfaces in the JDK that qualify?
【讨论】:
java.util.function 包中一共有 43 个接口。其中 35 个总结在下面的“常规”表格中(由于 StackOverflow 不支持 HTML 表格,因此以明文形式编写):
General 1
---------
-> Return Type
| R boolean void
V - ------- ----
T Function<T,R> Predicate<T> Consumer<T>
P int IntFunction<R> IntPredicate IntConsumer
a long LongFunction<R> LongPredicate LongConsumer
r double DoubleFunction<R> DoublePredicate DoubleConsumer
a T,U BiFunction<T,U,R> BiPredicate<T,U> BiConsumer<T,U>
m void Supplier<T> BooleanSupplier -
General 2
---------
-> Return Type
| int long double
V --- ---- ------
T ToIntFunction<T> ToLongFunction<T> ToDoubleFunction<T>
P int IntUnaryOperator IntToLongFunction IntToDoubleFunction
a long LongToIntFunction LongUnaryOperator LongToDoubleFunction
r double DoubleToIntFunction DoubleToLongFunction DoubleUnaryOperator
a T,U ToIntBiFunction<T,U> ToLongBiFunction<T,U> ToDoubleBiFunction<T,U>
m void IntSupplier LongSupplier DoubleSupplier
上面“常规”表中未包括的其余 8 个接口是:IntBinaryOperator、LongBinaryOperator、DoubleBinaryOperator、ObjIntConsumer<T>、ObjLongConsumer<T>、ObjDoubleConsumer<T>、UnaryOperator<T>、BinaryOperator<T>。它们如下表所示。为了便于比较,还显示了相关接口:
Operators
---------
-> Return Type
| R
V -
T Function<T,R>
UnaryOperator<T> = Function<T,T>
T,U BiFunction<T,U,R>
BinaryOperator<T> = BiFunction<T,T,T>
P
a int
r ---
a int IntUnaryOperator
m int,int IntBinaryOperator
e
t long
e ----
r long LongUnaryOperator
s long,long LongBinaryOperator
double
------
double DoubleUnaryOperator
double,double DoubleBinaryOperator
Consumers
---------
-> Return Type
| void
V ----
T Consumer<T>
int IntConsumer
long LongConsumer
P double DoubleConsumer
a T,U BiConsumer<T,U>
r T,int ObjIntConsumer<T>
a T,long ObjLongConsumer<T>
m T,double ObjDoubleConsumer<T>
Supplier<T>的类型参数在原源码中是T(T是抽象方法的返回类型)。但是,它适合此表中的 R 列,因为它实际上是相同的。
至于完成上表“General 1”的右下角输入,java.lang.Runnable可以认为是void-void接口。
UnaryOperator<T> 是Function<T,T> 的别名(Java 术语中的子接口)。
BinaryOperator<T> 是BiFunction<T,T,T> 的别名(Java 术语中的子接口)
以void 作为唯一参数的SAM(单一抽象方法)接口的名称中带有Consumer 后缀;
返回 void 的 SAM 接口的名称中有 Supplier 后缀;
返回 boolean 的 SAM 接口的名称中有 Predicate 后缀;
接受一个参数并返回相同类型的 SAM 接口在其名称中具有 UnaryOperator 后缀;
接受两个相同类型的参数并返回相同类型的 SAM 接口在其名称中具有 BinaryOperator 后缀;
所有其他接口的名称中都有Function 后缀;
带有两个不同类型参数的 SAM 接口在它们的前面有一个 Bi 前缀(如 BiConsumer、BiPredicate 和 BiFunction)。
上表的另一种格式(因为上表在移动设备中可能无法很好地显示):
P
一个
r
一个
米
T
int
long
double
T,U
无效
返回类型
R
------
函数
IntFunction
LongFunction
DoubleFunction
BiFunction
供应商
P
一个
r
一个
米
T
int
long
double
T,U
无效
返回类型
int
--------------------
ToIntFunction
IntUnaryOperator
LongToIntFunction
DoubleToIntFunction
ToIntBiFunction
IntSupplier
P
一个
r
一个
米
T
int
long
double
T,U
无效
返回类型
long
---------------------
ToLongFunction
IntToLongFunction
LongUnaryOperator
DoubleToLongFunction
ToLongBiFunction
LongSupplier
P
一个
r
一个
米
T
int
long
double
T,U
无效
返回类型
double
------------------------
ToDoubleFunction
IntToDoubleFunction
LongToDoubleFunction
DoubleUnaryOperator
ToDoubleBiFunction
DoubleSupplier
P
一个
r
一个
米
T
int
long
double
T,U
无效
返回类型
布尔值
----------------
谓词
IntPredicate
LongPredicate
DoublePredicate
BiPredicate
BooleanSupplier
P
一个
r
一个
米
T
int
long
double
T,U
无效
返回类型
void
---------------
Consumer
IntConsumer
LongConsumer
DoubleConsumer
BiConsumer
-
【讨论】:
BiSupplier接口,但是JDK中没有这样的接口。此外,根据定义,它会违反真正的功能规范——一个函数接受一个输入,然后返回一个输出。所以,要么你必须从这个接口返回一个元组(这可能是可以接受的),要么你必须有两个 get() 方法,这会很尴尬并且还会违反功能接口规范。因此,我建议您从表中完全删除提及的BiSupplier。除此之外,这是一个非常有用的表格,感谢您的努力。