Java8 函数式接口:Consumer、Function、Predictate
阅读数:153 评论数:0
跳转到新版页面分类
python/Java
正文
一、函数式编程和非函数编程的区别
(1)函数式编程:先考虑传入的参数,再考虑方法的实现。
(2)非函数编程:先定义好方法,再传入指定的参数
二、何为函数式接口
函数式接口(Functional Interface)就是一个有且仅有一个抽象方法(不包括默认、静态),这样可以与lambda表达式配合,但是可以有多个非抽象方法的接口。它通过@FunctionalInterface注解标注,该注解可用于一个接口的定义上,一旦使用该注解来定义接口,编译器将会强制检查该接口是否确实有且仅有一个抽象方法,否则将会报错。需要注意的是,即使不使用该注解,只要满足函数式接口的定义,这仍然是一个函数式接口,使用起来都一样。
@FunctionalInterface
interface GreetingService
{
void sayMessage(String message);
void doOtherWork(){
// Method body
}
void doOtherWork2(){
// Method body
}
}
函数式接口可以lambda表达式实现其抽象方法,如上面的方法可用lambda表达式表示
GreetingService greetingService = msg->System.out.println(msg);
greetingService.sayMessage("hello!");
三、Java8提供的常用函数式接口
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
// 为我们提供了一个链式的调用
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
// 链式调用示例
Consumer<Integer> calculate = x->System.out.println(x*2);
Consumer<Integer> calculate2 = x->System.out.println(x*3);
calculate.andThen(calculate2).accept(2);
如果查看List集合的相关源码,可以在顶级接口Iterable中看到它的身影。
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
// 使用
Arrays.stream(new int[5]).forEach(()->{});
上面的Consumer抽象函数是没有返回值的,而Function与Consumer最大的区别是该接口的抽象函数式有返回值。
@FunctionalInterface
public interface Function<T, R> {
// 接收一个泛型,返回一个泛型
R apply(T t);
// 链式处理,将上一次处理的结果作为下一次处理的参数
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
// 如compose相反,将调用者的结果作为参数处理的参数
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;
}
}
跟 Function很像,不过Predicate返回值是固定的boolean。
@FunctionalInterface
public interface Predicate<T> {
// 接收一个泛型参数,返回boolean
boolean test(T t);
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
default Predicate<T> negate() {
return (t) -> !test(t);
}
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);
}
}
相关推荐
consumer是非线程安全的,它不能在多线程中使用,所以在shutdownHook线程中不能使用consumer的close方法。如果你没有在程序退出前很好关闭consumer,最明显的行为主
afka在有新消费者加入或者撤出时,会触发rebalance操作,在subscribe订阅主题的时候,我们可以编写回掉函数,在触发rebalance操作之前和之后,提交相应偏移量和获取偏移量。<
一、概述
1、lambda允许把函数作为一个方法的参数。
二、取代某些匿名内部类
1、无参数函数的简写
如果需要创建一个线程,一种常见的写法是这样:
// JDK7 匿名内部类写法
new Threa
作用:使代码更简洁。
有些情况下,我们用lambda表达式仅仅是调用一些已经存在的方法,除了调用动作外,没有其他任何多余的动作,而通过方法引用可以使代码更简洁、更容易理解。
类型
语法
对应的L
一、概述
如果没有终端操作,中间操作是不会得到执行的(惰性求值)。
stream的使用可以将代码中大量的for循环变为简单的链式函数操作,但是需要注意性能,在数据量小的情况下二都相差不多,但是在数据
在JAVA5已经提供了Future和Callable的实现,可以用于阻塞式获取结果,如果想要异步获取结果,通常都会以轮询的方式去获取结果,如下:
<pre class="language
Supplier接口是JAVA8以后配合lambda表达式和函数式接口编程(FunctionInterface,以下简称FI)组合使用的一个接口。它最适合于表示工厂,简而言之,Supplier&