函数式接口
概述:有且仅有一个抽象方法的接口
函数式格式
(参数类型 参数名)->{代码块}
小括号中的参数列表和接口中抽象方法的参数列表一致
大括号中的代码其实就是以前实现抽象方法的方法体
接口格式:
@FunctionalInterface
修饰符 interface 接口名称 {
public abstract 返回值类型 方法名称(可选参数信息);
// 其他非抽象方法内容
}
@FunctionalInterface注解
一旦使用该注解来定义接口,编译器将会强制检查该接口是否确实有且仅有一个抽象方法,否则将会报错。需要注 意的是,即使不使用该注解,只要满足函数式接口的定义,这仍然是一个函数式接口,使用起来都一样。
使用Lambda作为参数和返回值
如果抛开实现原理不说,Java中的Lambda表达式可以被当作是匿名内部类的替代品。如果方法的参数是一个函数 式接口类型,那么就可以使用Lambda表达式进行替代。使用Lambda表达式作为方法参数,其实就是使用函数式 接口作为方法参数。
方法引用
方法特点:可推导可省略
方法引用符:
双冒号 :: 为引用运算符,而它所在的表达式被称为方法引用。如果Lambda要表达的函数方案已经存在于某个方法的实现中,那么则可以通过双冒号来引用该方法作为Lambda的替代者。
对象名引用成员方法:
对象名::方法名
//创建对象名
KeDiao kd=new KeDiao
diao(kd::方法名);
类名引用静态方法:
类名::方法名
Lambda表达式: n -> Math.abs(n)
方法引用: Math::abs
super引用父类成员方法:
super::方法名
this引用本类成员方法:
this::方法名
类的构造器的引用:
类名::new
数组构造器的引用
数据类型[]::new
常用函数式接口
Supplier 接口:生产接口 只有返回值没有参数(当需要获取一个数据的时候,就可以使用该接口)
接口仅包含一个无参的方法: T get() 。用来获取一个泛型参数指定类型的对 象数据。由于这是一个函数式接口,这也就意味着对应的Lambda表达式需要“对外提供”一个符合泛型类型的对象 数据。
import java.util.function.Supplier;
public class DemoIntArray {
public static void main(String[] args) {
int[] array = { 10, 20, 100, 30, 40, 50 };
printMax(() ‐> {
int max = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i] > max) {
max = array[i];
}
}
return max;
});
}
private static void printMax(Supplier<Integer> supplier) {
int max = supplier.get();
System.out.println(max);
}
}
Consumer 接口:消费接口 只有参数没有返回值
Consumer 接口则正好相反,它不是生产一个数据,而是消费一个数据,其数据类型由泛 型参数决定。
抽象方法:accept
Consumer 接口中包含抽象方法 void accept(T t) ,意为消费一个指定泛型的数据。
import java.util.function.Consumer;
public class Demo09Consumer {
private static void consumeString(Consumer<String> function) {
function.accept("Hello");
}
public static void main(String[] args) {
consumeString(s ‐> System.out.println(s));
consumeString(System.out::println);
}
}
默认方法:andThen
如果一个方法的参数和返回值全都是 Consumer 类型,那么就可以实现效果:消费一个数据的时候,首先做一个操 作,然后再做一个操作,实现组合。而这个方法就是 Consumer 接口中的default方法 andThen
源代码
default Consumer<T> andThen(Consumer<? super T> after) { Objects.requireNonNull(after);
return (T t) ‐> { this.accept(t); after.accept(t); };
}
例子:
import java.util.function.Consumer;
public class Demo10ConsumerAndThen {
private static void consumeString(Consumer<String> one, Consumer<String> two) {
one.andThen(two).accept("Hello");
}
public static void main(String[] args) {
consumeString(
s ‐> System.out.println(s.toUpperCase()),
s ‐> System.out.println(s.toLowerCase()));
}
}
predicate 接口 判断接口
什么时候使用:对某种类型的数据进行判断,从而得到一个boolean值结果
抽象方法:test
Predicate接口中包含一个抽象方法:boolean test(T t) 用于条件判断的场景
判断多个条件 使用Predicate接口中的默认方法
默认方法:and (&&)
既然是条件判断,就会存在与、或、非三种常见的逻辑关系,
其JDK源码为:
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
默认方法:or (||)
JDK源码为:
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
默认方法:negate (!)
JDK源码为:
default Predicate<T> negate() {
return (t) -> !test(t);
}
Function 接口
接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件。有进有出,所以称为“函数Function”。
抽象方法:apply
例如:将String 类型转换为Integer 类型
import java.util.function.Function;
public class Demo11FunctionApply {
private static void method(String strFunction<String, Integer> function) {
int num = function.apply(str);
System.out.println(num + 20);
}
public static void main(String[] args) {
String str="10"
method(str,s -> Integer.parseInt(s));
method(str,Integer::parseInt);
}
}
默认方法:andThen
用来进行组合操作,
JDK源代码:
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
例如:
import java.util.function.Function;
public class Demo12FunctionAndThen {
private static void method(String str,Function<String, Integer> one, Function<Integer, Integer> two) {
int num = one.andThen(two).apply(str);
System.out.println(num + 20);
}
public static void main(String[] args) {
String str="10"
method(str,Integer::parseInt, i -> i *= 10);
}
}