记忆java.util.function包下的接口
函数式接口是java8新加入的重大更新。了解了lambda表达式之后也要了解jdk中已经写好,给开发者调用的接口。这篇文章的目的帮助程序员记记java.util.function包下所有函数式接口。首先看看这个包下面接口的总量,嗯,一共43个,不少啊。
第一步
首先记住function包下的4个主要函数接口,我把它们叫作基本接口。其它的接口都是由这4个接口衍生来的,注意不是继承。
-
Function
这里的Function代表的含议其实就是中学学过的数学里的函数 y = f(x)。接口中定义的抽象方法是apply
,与数学中的定义一样,这个方法也是接收一个输入,返回一个输出。 -
Consumer
这是消费者函数,接口中定义的抽象方法是accept
。顾名恩义,接收一个参数,返回是void
, -
Supplier
这是生产者函数,接口中定义的抽象方法是get
。不接收参数,有一个返回。 -
Predicate
断言函数,接口中定义的抽象方法是test
。接收一个参数,返回true
或者false
。
其实存细想想这些接口定义的名称和接口的抽象方法都是具有含现实中的含义的,并不难记。4个接口者定义为范型,输要使用者自己传入。
目前记住了4个,还有39个。
第二步
我们观察前面的4个接口,发现除了Supplier
接口不需要输入,其它接口中的抽象方法接收一个输入,那么在实际的开发中接收两个输入的情况多不多呢?jdk作者认为接收两个输入的情况也很多,有必要再增加三个接口,接收两个输入。接口名称分别是BiFunction、BiConsumer、 BiPredicate
。这三个接口的抽象方法名称与上面的一样。唯一的区别就是接收输入的数量不同。
目前记住了7个,还剩下36个。
如果能记住这7个,实际上已经能充分利用这个java.util.function包下面定义的接口而不需要重新定义了,剩余的36个接口完成是为了方从方便的角度上定义的,是为了锦上添花。
第三步
再来看生产者函数,不接收输入,只有输出。
java一共有8种基本类型,或者叫原始类型(primitive type)分别是:byte short int long float double boolean char
。那么对于函数式接口每次使用的时候都用范型接口传入类型实在是太麻烦了。开发者对于原生类型的使用是最常见的,有必要为这些原生类型专门定义接口而不是每次都要开发者传入类型,这本来就是开发这些函数接口的目的。那么难道把所有的类型全部定义一遍吗,会产生大量的接口。jdk的开发者选择了4个最常用的原始类型,分别是int long double boolean
。对应的接口名称分别是IntSupplier LongSupplier DoubleSupplier BooleanSupplier
,对应的抽象方法名为getAsInt getAsLong getAsDouble getAsBoolean
。当然也很好记。
目前记住了11个,还剩下32个,而且把生产者接口全都记住了。
第四步
现在集中精力对付断言函数。基本断言函数的范型固定为int long double
,这样又多了3个衍生的断言函数。分别是IntPredicate LongPredicate DoublePredicate
,抽象方法名不变。当然接收的输入数据类型分别为int long double
。
目前记住了14个,还剩下29个,把断言接口全都记住了。
第五步
再来看消费者接口。jdk作者对于接收1个输入和2个输入的消费者接口都定义了特定的类型。
- 1个输入的消费者接口
定义了IntCustomer LongCustomer DoubleCustomer
接口,抽象方法名称不变。
- 2个输入的消费者接口
定义了ObjIntCustomer ObjLongCustomer ObjDoubleCustomer
接口。接口定义的2个类型分别为范型和相应类型的包装类。方法名称也不变。
目前记住了20个,还剩下23个,把消费者接口也全都记住了。
第六步
没错,剩下的23个全部都是函数类型的接口。在这一步中我们要记住所有一元函数接口
- 返回为范型,接收3种基本类型包装类
跟其它3种基本接口类型一样,也定义了IntFunction LongFunction DoubleFunction
,抽象方法名也不变。
- Integer作为输入,返回为2种基本类型包装类
定义了IntToLongFunction IntToDoubleFunction
,抽象方法名分别为applyAsLong applyAsDouble
。
- Long作为输入,返回为2个基本类型包装类
定义了LongToIntFunction LongToDoubleFunction
,抽象方法名分别为applyAsInt applyAsDouble
。
- Double作为输入,返回为2个基本类型包装类
定义了DoubleToIntFunction DoubleToLongFunction
,抽象方法名分别为applyAsInt applyAsLong
。
- 3种基本类型包装类作为输入,输出也是同样的类型
定义了IntUnaryOperator LongUnaryOperator DoubleUnaryOperator
,抽象方法名分别为applyAsInt applyAsLong applyAsDouble
。这里的Unary就是一元的意思,表示这个是一元函数。
- 范型作为输入,输出为范型和3种基本类型包装类
定义了ToIntFunction ToLongFunction ToDoubleFunction UnaryOperator
,抽象方法分别为applyAsInt applyAsLong applyAsDouble UnaryOperator
。
目前记住了36个,还剩下7个。
第七步
现在没有记住的接口只剩下接收2个输入的函数类型的接口了。
- 2个输入可以是不同范型,输入为3种基本类型包装类
定义了ToIntBiFunction ToLongBiFunction ToDoubleBiFunction
,抽象方法分别为applyAsInt applyAsLong applyAsDouble
- 2个输入和1个输出都是同一种类型,而且是范型
定义了BinaryOperator
,抽象方法为apply
。
- 2个输入和1个输出都是同一种类型,而且是3种基本类型包装类
定义了IntBinaryOperator LongBinaryOperator DoubleBinaryOperator
,抽象方法分别为applyAsInt applyAsLong applyAsDouble
。
总结
实际上这个包下面的所有接口逻辑都是非常清晰的,只要掌握了jdk作者的分类方法就完全能记住。
对于程序员来说要学会查文档,但是如果没有把一些常用的类和接口记在心里那么工作的效率就会变得很低。