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提供的常用函数式接口

1、Consumer(没有返回值)

@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(()->{});

2、Function

上面的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;
    }
}

3、Predicate

跟 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操作之前和之后,提交相应偏移量和获取偏移量。<

修饰接口中默认的方法实现(也就是接口中可以包含方法体,这打破了Java之前版本对接口的语法限制)。 public int

一、概述 1、lambda允许把函数作为一个方法的参数。 二、取代某些匿名内部类 1、无参数函数的简写 如果需要创建一个线程,一种常见的写法是这样: // JDK7 匿名内部类写法 new Threa

@FunctionalInterface public interface Predicate&lt;T&gt; { /**

作用:使代码更简洁。 有些情况下,我们用lambda表达式仅仅是调用一些已经存在的方法,除了调用动作外,没有其他任何多余的动作,而通过方法引用可以使代码更简洁、更容易理解。 类型 语法 对应的L

一、概述 如果没有终端操作,中间操作是不会得到执行的(惰性求值)。 stream的使用可以将代码中大量的for循环变为简单的链式函数操作,但是需要注意性能,在数据量小的情况下二都相差不多,但是在数据

在JAVA5已经提供了Future和Callable的实现,可以用于阻塞式获取结果,如果想要异步获取结果,通常都会以轮询的方式去获取结果,如下: <pre class="language

Supplier接口是JAVA8以后配合lambda表达式和函数式接口编程(FunctionInterface,以下简称FI)组合使用的一个接口。它最适合于表示工厂,简而言之,Supplier&

java8时,java.util.concurrent.atomic包中提供了一个新的原子类LongAddr,提供了原子累计值的方法,在高并发的场景下它比Ato