函数式接口
函数式接口是具有一个抽象方法的接口。
不能使用以下类型的方法来声明一个函数式接口:
- 默认方法
- 静态方法
- 从Object类继承的方法
一个函数式接口可以重新声明Object类中的方法。该方法不被视为抽象方法。Comparator接口有两个抽象方法:compare()
和equals()
。equals()
方法是Object类中的equals()
方法的重新声明。
@FunctionalInterface
interface Comparator<T>{
int compare(T o1, T o2);
boolean equals(Object obj);
}
@FunctionalInterface
@FunctionalInterface
注解定义java.lang包。使用它来标记一个函数式接口。
若@FunctionalInterface
在非函数式接口或其他类型(如类)上注释,则会发生编译时错误。
具有一个抽象方法的接口仍然是一个功能接口,即使我们不用@FunctionalInterface
注释。
通用函数式接口
使用类型参数与函数式接口定义通用函数式接口:
interface Calculator<T> {
int add(T a, T b);
}
使用抽象通用方法定义非通用函数式接口:
@FunctionalInterface
public interface Processor {
<T> void process(T[] list);
}
java.util.function包
Function<T,R>
作用:接受类型T
的参数并返回类型R
的结果的函数。
Function<T,R>接口的6个特殊化:
- IntFunction
- LongFunction
- DoubleFunciton
- ToIntFunction
- ToLongFunction
- ToDoubleFunction
IntFunction、LongFunction、DoubleFunction 分别以 int、long、double类型作为参数,以 R 作为返回值类型。
ToIntFunction、ToLongFunction、ToDoubleFunction 以T作为参数类型,分别返回int、long、double类型。
常用方法:
R apply(T t);
//创建一个Function,调用当前函数和指定的函数后得到结果
default <V> Function<T,V> andThen(Function<? super R,? extends V> after)
//创建一个Function,该函数调用指定的函数,然后调用当前函数并返回结果
default <V> Function<V,R> compose(Function<? super V,? extends T> before)
//创建一个返回其参数的函数
static <T> Function<T,T> identity()
BiFunction<T,U,R>
作用:接受类型T和U的两个参数,并返回类型R的结果。
BiFunction<T,U,R>接口的3个特殊化:
- ToIntBiFunction<T,U>
- ToLongBiFunction<T,U>
- ToDoubleBiFunction<T,U>
ToIntBiFunction<T,U>、ToLongBiFunction<T,U>、ToDoubleBiFunction<T,U> 接受两个参数,以T,U作为参数类型,分别返回int、long、double类型。
常用方法:
int applyAsInt(T t, U u);
Predicate<T>
作用:接受类型T的参数,返回true
或false
的布尔类型。
常用方法:
//对给定的参数计算此谓词。
boolean test(T t);
//否定原始谓词的谓词
default Predicate<T> negate()
//组合两个具有短路逻辑and的谓词
default Predicate<T> and(Predicate<? super T> other)
//组合了具有短路逻辑或的两个谓词
default Predicate<T> or(Predicate<? super T> other)
//返回一个谓词,根据Objects.equals(Object,Object)测试两个参数是否相等
static <T> Predicate<T> isEqual(Object targetRef)
例:
public class Demo_06_Predicate {
public static void main(String[] args) {
//判断num值是否大于2
Predicate<Integer> p1 = (num)-> num > 2;
System.out.println(p1.test(10));
//判断str字符串长度是否大于0且小于10
Predicate<String> p2 = (str)->str.length() > 0;
Predicate<String> p3 = (str)->str.length() < 10;
System.out.println(p2.and(p3).test("hello world!"));
}
}
BiPredicate<T,U>
作用:接受类型T和U的两个参数,返回true
或false
的布尔类型。
Consumer<T>
作用:接受类型T的参数,不返回结果。
BiConsumer<T,U>
作用:接受类型T,U的两个指定参数,不返回结果。
Supplier<T>
定义:Supplier接口也是用来创建对象的,但是不同于 new
,通过调用 get 方法间接调用构造方法创建一个新对象。
作用:返回类型T的值的函数。
UnaryOperator<T>
作用:接受参数并返回相同类型的结果的函数。
BinaryOperator<T>
作用:接受两个参数并返回相同类型的结果。
例:求两个数的最大值
public class Demo_20_BinaryOperator {
public static void main(String[] args) {
BinaryOperator<Integer> bo = (a, b) -> {
return a > b ? a : b;
};
System.out.println(bo.apply(10, 30));
}
}
交叉类型
Java 8引入了一种称为交集类型的新类型。交叉类型是多种类型的交叉。两种类型之间使用Type1 & Type2
,以表示类型1,类型2的交集的新类型。
注:交叉类型是解决lambda表达式不能直接赋值非函数式接口类型的一种方式
public class Demo_05 {
public static void main(String[] args) {
//为创建一个lambda表达式并赋值给非函数式接口 NonFunction 类型,可使用 & 来创建新的子类型(交叉类型)。
NoFunction noFunction = (NoFunction & Calculator) ((a, b) -> a * b);
System.out.println(noFunction);
//以这种方式,可以使一个lambda表达式可序列化
Serializable serializable = (Serializable & Calculator) ((a, b) -> a - b);
}
@FunctionalInterface
interface Calculator {
int calc(int a, int b);
}
//非函数式接口
interface NoFunction {
}
}