本文是我在学习函数式接口做的笔记,基于JDK8,如果有其他方法是基于后续版本的会用红色字体标注。
函数式接口也称为SAM接口,即Single Abstract Method interfaces。
特点
- 接口有且仅有一个抽象方法。
- 允许定义静态方法。
- 允许定义默认方法。
- 允许java.lang.Object中的public方法。
- 该注解不是必须的,如果一个接口符合"函数式接口"定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错。
函数式接口主要分为五类:Function,Consumer,Supplier,Predicate,Operator。这些五大类接口中的抽象方法都需要自己重写成自己需要的操作,如果不重写就调用,等于没做任何操作。
Function
直译为函数,用于对入参进行函数式操作。
Function接口有四个方法:
- R apply(T t):接受一个值,返回一个值。(可重写。)
- default <V> Function<V, R> compose(Function<? super V, ? extends T> before):默认方法,接受一个Function函数,返回一个Function函数。
- default <V> Function<T, V> andThen(Function<? super R, ? extends V> after):默认方法,接受一个Function函数,返回一个Function函数。
- static <T> Function<T, T> identity():静态方法,接受的值就是返回的值。
- compose和andThen的区别就像是f(g(x))和g(f(x))的区别。
代码示例如下:
Function<Integer, Integer> fx = x -> x + 1;
Function<Integer, Integer> gx = x -> x * 2;
Function<Integer, Integer> compose = fx.compose(gx); // f(g(x))
Function<Integer, Integer> andThen = fx.andThen(gx); // g(f(x))
int result1 = compose.apply(1);
int result2 = andThen.apply(1);
System.out.println(result1);// 3
System.out.println(result2);// 4
其他Function接口及特有方法:以下展示的方法都可以重写。
- BiFunction :R apply(T t, U u);接受两个参数,返回一个值。
- DoubleFunction :R apply(double value);只处理double类型。
- DoubleToIntFunction:int applyAsInt(double value);接受double类型,返回int类型。
- DoubleToLongFunction:long applyAsLong(double value);接受double类型,返回long类型。
- IntFunction :R apply(int value);只处理int类型。
- IntToDoubleFunction:double applyAsDouble(int value);接受int类型,返回double类型。
- IntToLongFunction:long applyAsLong(int value);接受int类型,返回long类型。
- LongFunction :R apply(long value);只处理long类型。
- LongToDoubleFunction:double applyAsDouble(long value);接受long类型,返回double类型。
- LongToIntFunction:int applyAsInt(long value);接受long类型,返回int类型。
- ToDoubleBiFunction:double applyAsDouble(T t, U u);接受两个参数,返回double类型。
- ToDoubleFunction:double applyAsDouble(T value);接受一个参数,返回double类型。
- ToIntBiFunction:int applyAsInt(T t, U u);接受两个参数,返回int类型。
- ToIntFunction:int applyAsInt(T value);接受一个参数,返回int类型。
- ToLongBiFunction:long applyAsLong(T t, U u);接受两个参数,返回long类型。
- ToLongFunction:long applyAsLong(T value);接受一个参数,返回long类型。
Consumer
直译消费者,用于对入参进行函数式操作。
Consumer接口有两个方法:
- void accept(T t):接受一个参数,并进行操作。(可重写。)
- default Consumer<T> andThen(Consumer<? super T> after):默认方法,接受一个Consumer函数,返回一个Consumer函数。
代码实例如下:
StringBuilder sb = new StringBuilder("Hello");
Consumer<StringBuilder> consumer1 = str -> str.append(" ");
Consumer<StringBuilder> consumer2 = str -> str.append("World!");
consumer1.andThen(consumer2).accept(sb);
System.out.println(sb);// Hello World!
其他Consumer接口及特有方法:以下展示的方法都可以重写。
- BiConsumer:void accept(T t, U u);接受两个参数。
- DoubleConsumer:void accept(double value);只处理double类型。
- IntConsumer:void accept(int value);只处理int类型。
- LongConsumer:void accept(long value);只处理long类型。
- ObjDoubleConsumer:void accept(T t, double value);接受一个泛型,一个double类型。
- ObjIntConsumer:void accept(T t, int value);接受一个泛型,一个int类型。
- ObjLongConsumer:void accept(T t, long value);接受一个泛型,一个long类型。
Supplier
直译为供应者,用于获取指定内容。
Supplier接口只有一个方法:
- T get();返回一个参数。(可重写。)
代码示例如下:
Supplier<String> supplier = () -> "Hello World!";
System.out.println(supplier.get());// Hello World!
其他Supplier接口及特有方法:以下展示的方法都可以重写。
- BooleanSupplier:boolean getAsBoolean();返回boolean类型。
- DoubleSupplier:double getAsDouble();返回double类型。
- IntSupplier:int getAsInt();返回int类型。
- LongSupplier:long getAsLong();返回long类型。
Predicate
直译为谓词,用于对入参进行判断是否符合指定条件。
Predicate接口有六个方法:
- boolean test(T t):接受一个参数,判断是否符合给定的条件。(可重写。)
- default Predicate<T> and(Predicate<? super T> other):默认方法,且操作,等价于条件A&&条件B。
- default Predicate<T> negate():默认方法,取反操作,等价于!条件A。
- default Predicate<T> or(Predicate<? super T> other):默认方法,或操作,等价于条件A||条件B。
- static <T> Predicate<T> isEqual(Object targetRef):静态方法,==操作,等价于A==B。
- static <T> Predicate<T> not(Predicate<? super T> target):静态方法,取反操作,等价于!条件A。该方法底层实现就是调用了一次negate方法。此方法JDK11之后版本可用。
代码示例如下:
Predicate<Integer> predicate = num -> num != 0;
// test
System.out.println(predicate.test(10));// true
// and
predicate = predicate.and(num -> num >= 1);
System.out.println(predicate.test(10));// true
// or
predicate = predicate.or(num -> num != 1);
System.out.println(predicate.test(10));// true
// negate
predicate = predicate.negate();
System.out.println(predicate.test(10));// false
// isEqual
Predicate<Integer> equal = Predicate.isEqual(10);
System.out.println(equal.test(10));// true
// not
Predicate<Integer> predicate2 = num -> num == 0;
Predicate<Integer> not = Predicate.not(predicate2);
System.out.println(not.test(0));// false
其他Predicate接口及特有方法:以下展示的方法都可以重写。
- BiPredicate:boolean test(T t, U u);接受两个参数。
- DoublePredicate:boolean test(double value);只处理double类型。
- IntPredicate:boolean test(int value);只处理int类型。
- LongPredicate:boolean test(long value);只处理long类型。
Operator
直译为操作员,可以看作是Function接口的补充。Operator分为两种,一种是UnaryOperator继承自Function,另一种是BinaryOperator继承自BiFunction。
UnaryOperator只有一个方法:
- static <T> UnaryOperator<T> identity():静态方法,接受的值就是返回的值。
代码示例如下:
UnaryOperator<Integer> identity = UnaryOperator.identity();
Integer apply = identity.apply(1);
System.out.println(apply);
BinaryOperator有两个方法:
- public static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator):公开静态方法,比较两个值哪个小。注意参数顺序,值大的在前面,值小的在后面。
- public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator):公开静态方法,比较两个值哪个大。值小的在前面,值大的在后面。
代码示例如下:
BinaryOperator<Integer> minBy = BinaryOperator.minBy(Integer::compare);
Integer min = minBy.apply(2, 1);
System.out.println(min); // 1
BinaryOperator<Integer> maxBy = BinaryOperator.maxBy(Integer::compare);
Integer max = maxBy.apply(1, 2);
System.out.println(max); // 2
其他Operator接口及特有方法:以下展示的方法都可以重写。
- DoubleBinaryOperator:double applyAsDouble(double left, double right);接受两个double类型,返回double类型。
- DoubleUnaryOperator:double applyAsDouble(double operand);接受一个double类型,返回double类型。
- IntBinaryOperator:int applyAsInt(int left, int right);接受两个int类型,返回int类型。
- IntUnaryOperator:int applyAsInt(int operand);接受一个int类型,返回int类型。
- LongBinaryOperator:long applyAsLong(long left, long right);接受两个long类型,返回long类型。
- LongUnaryOperator:long applyAsLong(long operand);接受一个long类型,返回long类型。
我只是学习了典型的几个方法,其他的方法没有尝试,但是这些方法是相似的,会一个,类比的就可以会其他的。