【03】四大函数式接口
一个接口中有且仅有一个抽象方法(注:可以包含多个默认方法及静态方法)
如果要自定义一个函数式接口的时候可以使用@FunctionalInterface标识接口为函数式接口,被@FunctionalInterface标识的接口 如果出现一个以上的抽象方法 注解会报错,用于提示
常见的函数式接口
Function<T, R> -> R apply(T t) : 传入一个类型T返回类型R
Lambda : change(1, x -> x + 3);
本次调用为传入int 返回int
方法引用 : change("123", Integer::parseInt);
本次调用为传入String 返回 Integer
public static <T, R> R change(T t, Function<T, R> function) {
return function.apply(t);
}
进阶方法
andThen : 先把参数作用于第一个函数,结果传递给第二个函数
如:Function<String, String> header = Letter::addHeader;
format("kaituozhe", header.andThen(Letter::addFooter));
注:如上代码会先对`kaituozhe`执行addHeader方法 然后对结果执行 addFooter方法
public static String format(String text, Function<String, String> function) {
return function.apply(text);
}
public class Letter {
public static String addHeader(String text) { return "--- Header --- \n" + text; }
public static String addFooter(String text) { return text + "\n--- Footer ---"; }
}
compose : 先把参数作用于第二个函数,其结果作用于第一个函数
注 : 通过debug会发现下面案例会先执行addHeader方法
如:Function<String, String> header = Letter::addHeader;
format("kaituozhe", header.compose(Letter::addFooter));
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
return (V v) -> apply(before.apply(v));
}
identity : 传入一个T返回一个T 原样返回
案例 : 如下两个案例效果是一样的
传入一个函数式接口 :
orangeList.stream()
.collect(Collectors.toMap(Orange::getWeight, e -> e));
使用Function接口中的静态方法 :
orangeList.stream()
.collect(Collectors.toMap(Orange::getWeight, Function.identity()));
static <T> Function<T, T> identity() {
return t -> t;
}
Consumer<T> -> void accept(T t) : 消费型接口 传入类型T
List<String> strList = Arrays.asList("a", "b", "c");
Lambda : strList.forEach(str -> System.out.println(str));
方法应用 : strList.forEach(System.out::println);
default void forEach(Consumer<? super T> action) {
for (T t : this) {
action.accept(t);
}
}
进阶方法
andThen : 先把参数作用于函数一进行执行,再把同样的参数作用于函数二进行执行
如 : 如下代码会先执行保存数据库函数 再 执行保存Redis函数
如果保存数据库失败 就不会执行到 保存Redis
Consumer<String> consumer = (obj) -> {
System.out.println(obj + " : 保存数据库");
throw new RuntimeException("");
};
consumer("订单", consumer.andThen((i) -> System.out.println(" : 保存Redis")));
public static <T> void consumer(T t, Consumer<T> consumer) {
consumer.accept(t);
}
Predicate<T> -> boolean test(T t) :用于判断 传入类型T 返回boolean
Lambda : isEmpty("", a -> a == null || a.equals(""))
方法引用 : isEmpty("", String::isEmpty)
参数二:在这次调用中表示需要传一个 入参为String类型返回为boolean类型的方法
public static <T> boolean isEmpty(T str, Predicate<T> predicate) {
return predicate.test(str);
}
进阶方法
and : 方法返回一个复合谓词,表示和另一个谓词的短路与关系
如:谓词1 &&(and) 谓词2
or : 方法返回一个复合谓词,表示和另一个谓词的短语或关系
如:谓词1 ||(or) 谓词2
如 : 取红色或绿色的橘子 并且他们大于150克 下面两个案例结果是一样的
案例1 :
orangeList.stream().filter(p.and(orange -> orange.getColor().equals("red"))
.or(orange -> orange.getColor().equals("green"))
.and(orange -> orange.getWeight() > 150)).collect(Collectors.toList());
案例2 :
orangeList.stream().filter(orange -> (orange.getColor().equals("red") ||
orange.getColor().equals("green")) &&
orange.getWeight() > 150).collect(Collectors.toList());
negate : 取反
如 : 取不是红色的橘子
orangeList.stream()
.filter(p.and(orange -> orange.getColor().equals("red")).negate())
.collect(Collectors.toList());
Predicate.isEqual : 把值跟函数中的值做比较,返回所有相匹配的
如: 返回所有红色
orangeList.stream().map(Orange::getColor)
.filter(Predicate.isEqual("red"))
.collect(Collectors.toList());
Supplier<T> -> T get() : 创建型 : 没有传入 返回类型T
Lambda : createBean(() -> new User());
方法引用 : createBean(User::new);
public static <T> T createBean(Supplier<T> supplier) {
return supplier.get();
}
关注我更好的学习技术
看完记得点赞