Java 函数式接口 Lambda

一、Lambda表达式需要“函数式接口”的支持

Lambda 的设计者们为了让现有的功能与 Lambda 表达式良好兼容,考虑了很多方法,于是产生了函数接口这个概念。
函数接口指的是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口,这样的接口可以隐式转换为 Lambda 表达式。
但是在实践中,函数式接口非常脆弱,只要某个开发者在该接口中添加一个函数,则该接口就不再是函数式接口进而导致编译失败。为了克服这种代码层面的脆弱性,并显式说明某个接口是函数式接口,Java 8 提供了一个特殊的注解@FunctionalInterface,举个简单的函数式接口的定义:

  1. @FunctionalInterface
  2. public interface GreetingService {
  3. void sayMessage(String message);
  4. }

Java7 只能通过匿名内部类进行编程,例如:

  1. GreetingService greetService = new GreetingService() {
  2. @Override
  3. public void sayMessage(String message) {
  4. System.out.println("Hello " + message);
  5. }
  6. };
  7. greetService.sayMessage("world");

Java8 可以采用 Lambda 表达方进行编程,例如:

  1. GreetingService greetService = message -> System.out.println("Hello " + message);
  2. greetService.sayMessage("world");

目前 Java 库中的所有相关接口都已经带有这个注解了,实践上java.lang.Runnablejava.util.concurrent.Callable是函数式接口的最佳例子!

  • 函数式接口:接口中只有一个抽象方法的接口,称为函数式接口。
  • 可以使用注解@FunctionalInterface 添加在该接口类上进行修饰,可以检查是否是函数式接口

    A.定义函数式接口

    ```java /**

    • Fun
    • encoding:UTF-8 *
    • @author Fcant 下午 14:51:50 2020/2/19/0019 */ @FunctionalInterface public interface Fun {

      Integer getValue(T t);

}

  1. <a name="2hMiL"></a>
  2. ### B.函数式接口的使用
  3. ```java
  4. // 函数式接口使用
  5. @Test
  6. public void funTest() {
  7. Integer op = op(1000, (x) -> x * x);
  8. System.out.println(op);
  9. }
  10. public Integer op(Integer in, Fun<Integer> fun) {
  11. return fun.getValue(in);
  12. }

二、Java四大内置核心函数式接口

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

1、四大核心内置接口

A.Consumer:消费型接口

  1. void accept(T t);
  1. // 1.Consumer<T> :消费型接口
  2. public void happyTest(double money, Consumer<Double> consumer) {
  3. consumer.accept(money);
  4. }
  5. @Test
  6. public void consumerTest() {
  7. happyTest(1000d, (x) -> System.out.println("本次消费:" + x + "元"));
  8. }

B.Supplier:供给型接口

  1. T get();
  1. // 2.Supplier<T> :供给型接口
  2. public List<Integer> getNumList(int n, Supplier<Integer> supplier) {
  3. List<Integer> list = new ArrayList<>();
  4. for (int i = 0; i < n; i++) {
  5. Integer num = supplier.get();
  6. list.add(num);
  7. }
  8. return list;
  9. }
  10. @Test
  11. public void supplierTest() {
  12. getNumList(10, () -> (int)(Math.random() * 100)).forEach(System.out::println);
  13. }

C.Function<T, R>:函数型接口

  1. R apply(T t);
  1. // 3.Function<T, R> :函数型接口
  2. public String strHandler(String s, Function<String, String> function) {
  3. return function.apply(s);
  4. }
  5. @Test
  6. public void strTest() {
  7. System.out.println(strHandler("gh", (s) -> s.toUpperCase()));
  8. }

D.Predicate:断言型接口

  1. boolean test(T t);
  1. // 4.Predicate<T> :断言型接口
  2. public List<String> filterStr(List<String> list, Predicate<String> predicate) {
  3. List<String> strings = new ArrayList<>();
  4. for (String s : list) {
  5. if (predicate.test(s)) {
  6. strings.add(s);
  7. }
  8. }
  9. return strings;
  10. }
  11. @Test
  12. public void strFilterTest() {
  13. List<String> stringList = Arrays.asList("Hello", "Fcant", "Lambda", "ww", "ok");
  14. filterStr(stringList, (s) -> s.length() > 3).forEach(System.out::println);
  15. }

2、其他接口

函数式接口 参数类型 返回值类型 包含的方法 用途
BiFunction<T, U, R> T,U R R apply(T t, U u); 对类型为T的对象应用操作
UnaryOperator<T>
(Function子接口)
T T T apply(T t); 返回类型为T的对象
BinaryOperator<T>
(BiFunction子接口)
T, T T T apply(T t1, T t2); 对类型为T的对象应用操作,并返回R类型的结果
BiConsumer<T, U> T, U void void accept(T t, U u); 确定类型为T的对象是否满足某约束,并返回boolean值
ToIntFunction<T>
ToLongFunction<T>
ToDoubleFunction<T>
T int
long
double
分别计算int,long,double、值的函数
IntFunction<R>
LongFunction<R>
DoubleFunction<R>
int
long
double
R 参数分别为int,long,double类型的函数