函数式接口学习笔记
函数式接口
标注为FunctionalInterface的接口被称为函数式接口,该接口只能有一个自定义方法,但是可以包括从object类继承而来的方法。如果一个接口只有一个方法,则编译器会认为这就是一个函数式接口。是否是一个函数式接口,需要注意的有以下几点:
- 该注解只能标记在”有且仅有一个抽象方法”的接口上。
- JDK8接口中的静态方法和默认方法,都不算是抽象方法。
- 接口默认继承java.lang.Object,所以如果接口显示声明覆盖了Object中方法,那么也不算抽象方法。
- 该注解不是必须的,如果一个接口符合”函数式接口”定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错。
- 在一个接口中定义两个自定义的方法,就会产生Invalid ‘@FunctionalInterface’ annotation; FunctionalInterfaceTest is not a functional interface错误。
Function接口
接口说明
/**
* 一个入参,和一个返回参数
*/
R apply(T t);
/**
* 返回一个先执行before函数对象apply方法再执行当前函数对象apply方法的函数对象
*/
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
/**
* 返回一个先执行当前函数对象apply方法再执行after函数对象apply方法的函数对象。
*/
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
/**
* 返回一个函数,此函数入参值是什么,出参为什么
*/
static <T> Function<T, T> identity() {
return t -> t;
}
Java已有接口
Arrays::asList
应用
package com.lin.function.function;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
public class TestFunction {
public static void main(String[] args) {
Function<Integer,Integer> func1 = e->e*2;
Function<Integer,Integer> func2 = e->e+2;
System.out.println(func2.andThen(func1).apply(3));
System.out.println(func2.compose(func1).apply(3));
List<String[]> list = new ArrayList<String[]>();
String[] a = {"a1","a2","a3"};
String[] b = {"b1","b2"};
String[] c = {"c1","c2","c3"};
list.add(a);
list.add(b);
list.add(c);
list.stream().map(Arrays::asList).forEach(System.out::println);
}
}
扩展
Function接口是一个入参,一个出参。
1) 当入参和出参为基本类型int、long和double,会新增12种扩展
① 入参为基本类型,出参为自定义
IntFunction:入参为int,出参自定义,以此类推,LongFunction和DoubleFunction
② 入参为自定义,出参为基本类型
ToIntFunction:出参为int,入参自定义,以此类推,ToLongFunction和ToDoubleFunction
③ 入参和出参都为基本类型
IntToDoubleFunction:入参为int,出参为double,以此类推IntToLongFunction、LongToIntFunction、LongToDoubleFunction、DoubleToIntFunction、DoubleToLongFunction
2) 当入参为2个,出参为1个,新增4种扩展
BiFunction:入参2个,出参1个
ToIntBiFunction:入参2个自定义,出参为int,以此类推ToIntLongFunction和ToDoubleBiFunction
Predicate
接口说明
/**
* 一个入参,出参为boolean类型
*/
boolean test(T t);
/**
*且操作,既满足A也满足B条件
*/
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
/**
*取反操作 为true则返回false
*/
default Predicate<T> negate() {
return (t) -> !test(t);
}
/**
*或操作,满足A条件或者满足B条件
*/
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
/**
*静态方法,判定是否相等
*/
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
Java已有接口
Collection::isEmpty
应用
package com.lin.function.predicate;
import java.util.function.Predicate;
public class TestPredicate {
public static void main(String[] args) {
Predicate<Integer> p1 = e->e<10;//小于10的条件
Predicate<Integer> p2 = e->e>5;//大于5的条件
System.out.println(p1.and(p2).test(8));
System.out.println(p1.or(p2).test(8));
System.out.println(p1.negate().test(8));
}
}
扩展
Predicate接口是一个入参,出参boolean。
1) 当入参为基本类型int、long和double,会新增3种扩展
IntPredicate表示入参为int。以此类推LongPredicate和DoublePredicate。
2) 当入参为2个时,会新增1种扩展
BiPredicate。
Consumer接口
接口说明
/**
一个入参,没有出参接口
*/
void accept(T t);
/**
* 返回一个先执行当前函数对象apply方法再执行after函数对象apply方法的函数对象。
*/
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
Java已有接口
System.out::println
应用
package com.lin.function.consumer;
import java.util.function.Consumer;
public class TestConsumer {
public int a = 1;
public static void main(String[] args) {
Consumer<TestConsumer> consumer1 = e-> e.a = e.a+1;
Consumer<TestConsumer> consumer2 = e-> e.a = e.a*2;
TestConsumer old = new TestConsumer();
old.a = 1;
consumer1.accept(old);
System.out.println(old.a);
consumer1.andThen(consumer2).accept(old);
System.out.println(old.a);
}
}
扩展
Consumer接口是一个入参,没有出参。
1) 当入参为基本类型int、long和double,会新增3种扩展
IntConsumer,入参为int。以此类推,LongConsumer和DoubleConsumer。
2) 当入参2个,分别是一个泛型和一个基本类型int、long和double,会新增3种扩展
ObjIntConsumer,入参为泛型T和int。以此类推,ObjLongConsumer和ObjDoubleConsumer。
3) 当入参2个,分别都是泛型,会新增1种扩展
BiConsumer,入参为2个,都为泛型。
Supplier
接口说明
/**
* 一个泛型出参,没有入参
*/
T get();
Java已有接口
Instant::now
应用
package com.lin.function.supplier;
import java.util.function.Supplier;
public class TestSupplier {
public static void main(String[] args){
Supplier<String> sup = ()->"abc";
System.out.println(sup.get());
}
}
扩展
Supplier是一个只有出参,没有入参接口。
当出参是基本数据类型boolean、int、long、double时,有4种扩展分别是BooleanSupplier、IntSupplier、LongSupplier和DoubleSupplier。
UnaryOperator
接口说明
UnaryOperator接口继承了Function接口,也是一个入参一个出参。特殊的地方是UnaryOperator接口的入参和出参是同一类型。
public interface UnaryOperator<T> extends Function<T, T>
/**
* 入参和出参都是同一个类型
*/
T apply(T t);
Java已有接口
String::toLowerCase
应用
package com.lin.function.unaryOperator;
import java.util.function.UnaryOperator;
public class TestUnaryOperator {
public static void main(String[] args) {
UnaryOperator<Integer> uop1 = e-> e+3;
UnaryOperator<Integer> uop2 = e-> e*2;
System.out.println(uop1.andThen(uop2).apply(2));
System.out.println(uop1.compose(uop2).apply(2));
System.out.println(UnaryOperator.identity().apply(2));
}
}
扩展
UnaryOperator接口是一个入参和一个出参,入参和出参是同一种类型。当类型为基本类型int、long和double时,有三种扩展,分别是IntUnaryOperator、LongUnaryOperator和DoubleUnaryOperator。
BinaryOperator
接口说明
BinaryOperator接口继承BiFunction接口,BiFunction接口是Function接口的扩展,有2个入参和1个出参。BinaryOperator接口是BiFunction接口的特殊情况,当入参和出参的数据类型相同时,就是BinaryOperator。
public interface BinaryOperator<T> extends BiFunction<T,T,T>
除了继承BiFunction接口里面的方法外,BinaryOperator接口还实现一下2个静态方法:
/**
* 接收一个比较实现,获取最小值。
*/
public static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) {
Objects.requireNonNull(comparator);
return (a, b) -> comparator.compare(a, b) <= 0 ? a : b;
}
/**
*接收一个比较实现,获取最大值。
*/
public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) {
Objects.requireNonNull(comparator);
return (a, b) -> comparator.compare(a, b) >= 0 ? a : b;
}
Java已有接口
BigInteger::add
应用
package com.lin.function.binaryOperator;
import java.util.function.BinaryOperator;
public class TestBinaryOperator {
public static void main(String[] args) {
BinaryOperator<Integer> addOperator = (a,b)->a+b;
BinaryOperator<Integer> subOperator = (a,b)->a-b;
System.out.println(addOperator.apply(4, 2));
System.out.println(subOperator.apply(4, 2));
System.out.println(BinaryOperator.maxBy((Integer a, Integer b)->a.compareTo(b)).apply(4, 5));
System.out.println(BinaryOperator.minBy((Integer a, Integer b)->a.compareTo(b)).apply(4, 5));
}
}
扩展
BinaryOperator有2个入参和1个出参,而且入参和出参的数据类型一样。如果数据类型为基本类型int、long和double时,有3种扩展,分别是IntBinaryOperator、LongBinaryOperator和DoubleBinaryOperator。