函数式接口(Functional Interface)

函数式接口(Functional Interface)

简介

它是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
函数式接口可以被隐式转换为 lambda 表达式。

Lambda 表达式和方法引用(实际上也可认为是Lambda表达式)上。

如定义了一个函数式接口如下:

public class GreetingDemo {
    
    
    @FunctionalInterface
    interface GreetingInterface {
    
    
        void sayMessage(String message);
    }

    public static void main(String[] args) {
    
    
        GreetingInterface greetingInterface = message -> {
    
    
            System.out.println("Hello " + message);
        };
        greetingInterface.sayMessage("Tom");
    }
}

输出即为:Hello Tom

function包下的函数式接口

java.util.function 它包含了很多类,用来支持 Java的 函数式编程,该包中的函数式接口有

序号 接口 & 描述
1 BiConsumer<T,U> 代表了一个接受两个输入参数的操作,并且不返回任何结果
2 BiFunction<T,U,R> 代表了一个接受两个输入参数的方法,并且返回一个结果
3 BinaryOperator 代表了一个作用于于两个同类型操作符的操作,并且返回了操作符同类型的结果
4 BiPredicate<T,U> 代表了一个两个参数的boolean值方法
5 BooleanSupplier 代表了boolean值结果的提供方
6 Consumer 代表了接受一个输入参数并且无返回的操作
7 DoubleBinaryOperator 代表了作用于两个double值操作符的操作,并且返回了一个double值的结果。
8 DoubleConsumer 代表一个接受double值参数的操作,并且不返回结果。
9 DoubleFunction 代表接受一个double值参数的方法,并且返回结果
10 DoublePredicate 代表一个拥有double值参数的boolean值方法
11 DoubleSupplier 代表一个double值结构的提供方
12 DoubleToIntFunction 接受一个double类型输入,返回一个int类型结果。
13 DoubleToLongFunction 接受一个double类型输入,返回一个long类型结果
14 DoubleUnaryOperator 接受一个参数同为类型double,返回值类型也为double 。
15 Function<T,R> 接受一个输入参数,返回一个结果。
16 IntBinaryOperator 接受两个参数同为类型int,返回值类型也为int 。
17 IntConsumer 接受一个int类型的输入参数,无返回值 。
18 IntFunction 接受一个int类型输入参数,返回一个结果 。
19 IntPredicate :接受一个int输入参数,返回一个布尔值的结果。
20 IntSupplier 无参数,返回一个int类型结果。
21 IntToDoubleFunction 接受一个int类型输入,返回一个double类型结果 。
22 IntToLongFunction 接受一个int类型输入,返回一个long类型结果。
23 IntUnaryOperator 接受一个参数同为类型int,返回值类型也为int 。
24 LongBinaryOperator 接受两个参数同为类型long,返回值类型也为long。
25 LongConsumer 接受一个long类型的输入参数,无返回值。
26 LongFunction 接受一个long类型输入参数,返回一个结果。
27 LongPredicate R接受一个long输入参数,返回一个布尔值类型结果。
28 LongSupplier 无参数,返回一个结果long类型的值。
29 LongToDoubleFunction 接受一个long类型输入,返回一个double类型结果。
30 LongToIntFunction 接受一个long类型输入,返回一个int类型结果。
31 LongUnaryOperator 接受一个参数同为类型long,返回值类型也为long。
32 ObjDoubleConsumer 接受一个object类型和一个double类型的输入参数,无返回值。
33 ObjIntConsumer 接受一个object类型和一个int类型的输入参数,无返回值。
34 ObjLongConsumer 接受一个object类型和一个long类型的输入参数,无返回值。
35 Predicate 接受一个输入参数,返回一个布尔值结果。
36 Supplier 无参数,返回一个结果。
37 ToDoubleBiFunction<T,U> 接受两个输入参数,返回一个double类型结果
38 ToDoubleFunction 接受一个输入参数,返回一个double类型结果
39 ToIntBiFunction<T,U> 接受两个输入参数,返回一个int类型结果。
40 ToIntFunction 接受一个输入参数,返回一个int类型结果。
41 ToLongBiFunction<T,U> 接受两个输入参数,返回一个long类型结果。
42 ToLongFunction 接受一个输入参数,返回一个long类型结果。
43 UnaryOperator 接受一个参数为类型T,返回值类型也为T。

几种常见的函数式接口

Consumer

Represents an operation that accepts a single input argument and returns no result.
源码如下,

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

使用方法示例如下,

import java.util.function.BiConsumer;
import java.util.function.Consumer;

public class ConsumerDemo {
    
    
    public static void main(String[] args) {
    
    
        Consumer<String> f = System.out::println;
        Consumer<String> f2 = n -> System.out.println(n + "F2");

        // 执行完f后再执行f2的Accept方法
        f.andThen(f2).accept("test");

        // 连续执行f2的Accept方法
        f2.andThen(f2).andThen(f2).accept("test1");

        BiConsumer<String, String> f3 = (x, y) -> System.out.println(x + "," + y);
        f3.accept("x=5", "y=6");
    }
}

输出结果如下,
在这里插入图片描述

Function

Represents a function that accepts one argument and produces a result.
源码如下,

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

使用示例如下,

import java.util.function.BiFunction;
import java.util.function.Function;

public class FunctionDemo {
    
    
    public static void main(String[] args) {
    
    
        Function<Integer, Integer> f = s -> ++s;
        Function<Integer, Integer> g = s -> s * 2;

        // 先执行g再执行f,3*2 +1 = 7
        System.out.println(f.compose(g).apply(3));
        // 先执行f再执行g,(3+1)*2 = 8
        System.out.println(f.andThen(g).apply(3));
        // identify方法会返回一个不进行处理的Function,即输出和输入值相等
        System.out.println(Function.identity().apply("a"));

        // 泛型中第一个第二个为输入类型,第三个为输出类型
        BiFunction<String, String, Integer> biFunction = (x, y) -> Integer.parseInt(x) + Integer.parseInt(y);
        System.out.println(biFunction.apply("51", "94"));
    }
}

输出结果如下,
在这里插入图片描述

Predicate

Represents a predicate (boolean-valued function) of one argument.
源码如下,

@FunctionalInterface
public interface Predicate<T> {
    
    
    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);
    }
}

使用示例如下,

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.junit.Assert;

import java.util.function.Predicate;
import java.util.stream.Stream;

public class PredicateDemo {
    
    
    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
    @Data
    static class Gift {
    
    
        private String name;
        private int price;
    }

    public static void main(String[] args) {
    
    
        Predicate<String> p = "test"::equals;
        Predicate<String> g = o -> o.startsWith("t");
        // negate:用于对原来的Predicate做取反处理;
        Assert.assertFalse(p.negate().test("test"));
        // 针对同一个输入值,多个Predicate均返回true时返回true,否则返回false
        Assert.assertTrue(p.and(g).test("test"));
        // 针对同一个输入值,多个Predicate只要有一个返回true则返回true,否则返回false
        Assert.assertTrue(p.or(g).test("test"));

        Gift exceptGift = new Gift("Ps4", 1000);
        Predicate<Gift> predicate = Predicate.isEqual(exceptGift);
        System.out.println(
                Stream.of(
                        Gift.builder().name("egg").price(1).build(),
                        Gift.builder().name("apple").price(3).build(),
                        Gift.builder().name("Ps4").price(1000).build(),
                        Gift.builder().name("banana").price(2).build(),
                        Gift.builder().name("Ps4").price(1000).build(),
                        Gift.builder().name("belt").price(20).build(),
                        Gift.builder().name("Ps4").price(1000).build(),
                        Gift.builder().name("book").price(50).build()
                ).filter(predicate).count()
        );
    }
}

Supplier

Represents a supplier of results.
源码如下,

@FunctionalInterface
public interface Supplier<T> {
    
    
    T get();
}

Supplier看起来应该是最简单的一个函数式接口,下面看看怎么用它,

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.function.Supplier;

public class SupplierDemo {
    
    
    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
    @Data
    static class Product {
    
    
        private String name;

        private String expiration = currentDateTime();
    }

    public static void main(String[] args) {
    
    
        Supplier<Product> supplier = Product::new;
        System.out.println(supplier.get().expiration);
    }

    private static String currentDateTime() {
    
    
        long millis = System.currentTimeMillis();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
        return format.format(millis);
    }
}

输出结果如下,
在这里插入图片描述

总结

上面介绍了几个简单的函数式接口以及该函数式接口如何使用,引入函数式接口在一定程度上可以提高编码效率,使用过程也更加简便。需要开发者自行熟悉。

如果感兴趣的可以思考一下函数式接口在效率上是否更快呢?

可以先去查看编译后的class文件,以上面的ConsumerDemo为例,对应的ConsumerDemo.class文件代码如下,

package com.hust.zhang.functional;

import java.io.PrintStream;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

public class ConsumerDemo {
    
    
    public ConsumerDemo() {
    
    
    }

    public static void main(String[] args) {
    
    
        PrintStream var10000 = System.out;
        Consumer<String> f = var10000::println;
        Consumer<String> f2 = (n) -> {
    
    
            System.out.println(n + "F2");
        };
        f.andThen(f2).accept("test");
        f2.andThen(f2).andThen(f2).accept("test1");
        BiConsumer<String, String> f3 = (x, y) -> {
    
    
            System.out.println(x + "," + y);
        };
        f3.accept("x=5", "y=6");
    }
}

再使用javap -c ConsumerDemo.class反编译class文件看看源码如下,

public class com.hust.zhang.functional.ConsumerDemo {
    
    
  public com.hust.zhang.functional.ConsumerDemo();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: dup
       4: invokevirtual #3                  // Method java/lang/Object.getClass:()Ljava/lang/Class;
       7: pop
       8: invokedynamic #4,  0              // InvokeDynamic #0:accept:(Ljava/io/PrintStream;)Ljava/util/function/Consumer;
      13: astore_1
      14: invokedynamic #5,  0              // InvokeDynamic #1:accept:()Ljava/util/function/Consumer;
      19: astore_2
      20: aload_1
      21: aload_2
      22: invokeinterface #6,  2            // InterfaceMethod java/util/function/Consumer.andThen:(Ljava/util/function/Consumer;)Ljava/util/function/Consumer;
      27: ldc           #7                  // String test
      29: invokeinterface #8,  2            // InterfaceMethod java/util/function/Consumer.accept:(Ljava/lang/Object;)V
      34: aload_2
      35: aload_2
      36: invokeinterface #6,  2            // InterfaceMethod java/util/function/Consumer.andThen:(Ljava/util/function/Consumer;)Ljava/util/function/Consumer;
      41: aload_2
      42: invokeinterface #6,  2            // InterfaceMethod java/util/function/Consumer.andThen:(Ljava/util/function/Consumer;)Ljava/util/function/Consumer;
      47: ldc           #9                  // String test1
      49: invokeinterface #8,  2            // InterfaceMethod java/util/function/Consumer.accept:(Ljava/lang/Object;)V
      54: invokedynamic #10,  0             // InvokeDynamic #2:accept:()Ljava/util/function/BiConsumer;
      59: astore_3
      60: aload_3
      61: ldc           #11                 // String x=5
      63: ldc           #12                 // String y=6
      65: invokeinterface #13,  3           // InterfaceMethod java/util/function/BiConsumer.accept:(Ljava/lang/Object;Ljava/lang/Object;)V
      70: return
}

参考链接:https://www.runoob.com/java/java8-functional-interfaces.html

猜你喜欢

转载自blog.csdn.net/zkkzpp258/article/details/129510029