Java8 | 函数式接口

一、什么是函数式接口

函数式接口便是只包含一个抽象方法的接口,它包含以下内容

  • 可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda 表达式抛出一个非运行时异常 ,那么该异常需要在目标接口的抽象方法上进行声明)
  • 可以在一个接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口,同时 javadoc 也会包含一条生命,说明该接口是一个函数式接口
  • 在 java.util.function 包下定义了很多 Java8 的函数式接口

简单的说,在 Java8 中, Lambda 表达式就是一个函数接口的实例。 这就是 Lambda 表达式和函数接口的关系。也就是说,只要一个对象是函数式接口的实例,那么该对象就可以用 Lambda 表达式来表示

自己定义一个函数式接口,需要在接口上加 @FunctionalInterface 注解,同时该接口只有一个抽象方法

@FunctionalInterface
public interface MyInterface {

    String method();

}

二、Java内置的函数式接口

Java内置了四大核心的函数式接口

函数式接口 参数类型 返回类型 用途
Consumer 消费型接口 T void 对类型为T的对象应用操作,包含方法:void accept(T t)
Supplier 供给型接口 T 返回类型为 T 的对象,包含方法:T get()
Function 函数型接口 T R 对类型为T的对象应用操作,并返回结果是R类型的对象,包含方法:R apply(T t)
Predicate 断定型接口 T boolean 确定类型为T的对象是否满足某约束,并返回boolean 值,包含方法:boolean test(T t)

1. 消费型接口

消费型接口里的唯一一个抽象方法,只有参数,没有返回值(参数类比花钱,返回值类比钱花完了?)

@Test
public void testConsumer() {
    handleMoney(100.22, new Consumer<Double>() {
        @Override
        public void accept(Double aDouble) {
            // 重写 accept 方法,输出传入的值
            System.out.println("花了" + aDouble);
        }
    });

    handleMoney(100, money -> System.out.println("花了" + money));
}

// 调用 handleMoney 方法时,执行 accept 方法时,去匿名内部类中重写的 accept 方法中寻找执行该方法的代码
public void handleMoney(double money, Consumer<Double> consumer) {
    // accept 方法表示传入 money
    consumer.accept(money);
}

accept 方法只能传入值,没有返回值,表示只能花钱


2. 供给型接口

供给型接口的唯一一个抽象方法,没有参数,有返回值(没有参数类比不需要花钱,有返回值类比别人会给你钱)

@Test
public void testSupplier() {
    Random random = new Random();

    List<Integer> supplier = supplier(10, new Supplier<Integer>() {
        @Override
        public Integer get() {
            // 重写的 get 方法,传入随机数
            return random.nextInt(10);
        }
    });

    for (Integer integer : supplier) {
        System.out.printf(integer + " ");
    }
    
    // Lambda 表达式
    List<Integer> supplier1 = supplier(10, () -> random.nextInt(10));

    for (Integer integer : supplier1) {
        System.out.printf(integer + " ");
    }
}

public List<Integer> supplier(int num, Supplier<Integer> supplier) {
    List<Integer> list = new ArrayList<>();

    for (int i = 0; i < num; i++) {
        // 从 get 方法中获取值
        list.add(supplier.get());
    }

    return list;
}

3. 函数型接口

函数型接口的唯一一个抽象方法,是 R apply(T t),表示对类型 T 的对象应用操作,返回 R 类型的对象

@Test
public void testFunction() {
    Integer len = strOperate("luwenhe", new Function<String, Integer>() {
        @Override
        public Integer apply(String s) {
            // 重写 apply 方法,这里表示传入 String 类型的对象,返回 String 字符串的长度
            return s.length();
        }
    });
    System.out.println(len);

    strOperate("luwenhe", s -> s.length());
}

/**
  * 字符串操作
  * @param string    需要传入的字符串
  * @param function  Function 接口
  * @return          处理之后的字符串
  */
public Integer strOperate(String string, Function<String, Integer> function) {
    // 传入 string 类型的参数,返回结果
    return function.apply(string);
}

函数式接口表示,传入一个类型的参数的,输出一个类型的参数,这两种类型可以一样


4. 断定型接口

断定型接口的唯一一个抽象方法 boolean test(T t),该方法传入一个类型的参数,返回一个 boolean 类型的值

public void testPredicate() {
    List<Integer> list = Arrays.asList(1, 5, 10, 15, 20, 30);

    List<Integer> integers = filterInteger(list, new Predicate<Integer>() {
        @Override
        public boolean test(Integer integer) {
            // 重写 test 方法,这里表示判断传入的值是否大于 5,如果大于 5 则返回 true,否则返回 false
            return integer > 5;
        }
    });

    for (Integer integer : integers) {
        System.out.println(integer + " ");
    }

    // Lambda 表达式
    List<Integer> integers1 = filterInteger(list, integer -> (integer > 10));

    for (Integer integer : integers1) {
        System.out.println(integer + " ");
    }
}

public List<Integer> filterInteger(List<Integer> list, Predicate<Integer> predicate) {
    List<Integer> list1 = new ArrayList<>();

    for (Integer integer : list) {
        // 传入一个 Integer 类型的值,经过 test 方法的判断,返回 true 或者 false
        if (predicate.test(integer)) {
            list1.add(integer);
        }
    }

    return list1;
}

三、参考

https://www.cnblogs.com/wuyx/p/9000312.html

你可能感兴趣的:(Java8)