一、前言

早期的程序员在JDK1.5时期,掌握泛型、枚举、反射 基本上就可以了,随着JDK不断迭代升级,到相对于稳定的JDK1.8版本,扩展了大量的知识点,例如:lambda表达式,链式编程,函数式接口,Stream流式计算  这些新知识点的出现大大的简化了编程模型,减少了很多冗余代码,代码简洁,清晰明了,并且在迭代出来的底层架构大量得到了应用,所以,我们必须随着主流进行学习,避免阅读源码时都不知道其意。

二、函数式接口(Functional Interface)

函数式接口:只有一个方法的接口

有且仅有一个抽象方法的接口,但是可以有多个非抽象方法的接口。函数式接口可以被隐式转换为 lambda 表达式。Lambda就是Java中函数式编程的体现。

|类型

主要分布在 java.util.function 包下,常见的 4大原始函数 接口为:Function (函数型接口)、Predicate (断定型接口)、Consumer (消费型接口)、Supplier (供给型接口)

|@FunctionalInterface注解

Java 8中专门为函数式接口引入了一个新的注解:@FunctionalInterface 。该注解放在接口上,表示此接口是一个函数式接口。并且提示编译器去检查接口是否仅包含一个抽象方法,即,是否符合函数式编程的定义。

注意:如果自定义一个符合规范的函数式接口,也可以不加@FunctionalInterface注解,此注解只是起到一个提示编译器进行规范检查的作用

日常开发中用的最多的函数式接口的,比如线程中的 Runnable

@FunctionalInterface
public interface Runnable {public abstract void run();
}

1. Function (函数型接口)

有一个输入参数,有一个输出

接口的源码如下:

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

apply ()方法就是该接口的唯一方法,也就是继承该Function接口,唯一需要实现的方法!

有小伙伴可能还会问,函数式接口不是 有且只有一个方法 吗?为什么存在default 和 static的方法

  • static:实现接口的类或子接口不会继承接口里的静态方法!
  • default:java8在接口中新增default方法,是为了在现有的类库中新增功能而不影响其实现类,也就是说,该接口的实现类可以直接调用default方法,而不需要实现它!

我们来具体使用下该接口

// 输出输入的参数:有一个输入参数,和一个输出
public static void main(String[] args) {// 1. 初始化,并且实现该接口的唯一实现方法Function<String,String> function = new Function<String, String>() {@Overridepublic String apply(String str) {return str;}};System.out.println(function.apply("abc"));
}

执行结果:str是一个参数传递到 Predicate 接口的 apply 方法 。表示接受一个参数并产生结果

这就是一个标准的函数式接口,我们前面也说了:Lambda就是Java中函数式编程的体现  也就是说只要是函数式接口,就可以使用lambda表达式来简化代码!如下:

public static void main(String[] args) {// 使用lambda表达式Function<String,String> function = (str)->{return str;};//或者我们可以更简单点,把str的()括号去掉也是可以的// Function<String,String> function = str->{return str;};System.out.println(function.apply("abc"));
}

这就是典型的lambda表达式语法:()->{};str是传入的参数,等同于我们线程中的Runnable用法:

// Thread内部是一个Runnable的函数式接口,run()是Runnable接口中唯一的方法
Thread thread = new Thread(new Runnable() {@Overridepublic void run() {System.out.println(1);}
});// 上述代码等同于:
Thread thread2 = new Thread(()->{System.out.println(1);});

2. Predicate (断定型接口)

有一个输入参数,返回值只能是布尔值

源码如下:

@FunctionalInterface
public interface Predicate<T> {// 在给定的参数上评估这个谓词boolean test(T t);
}

具体使用:

public static void main(String[] args) {/* Predicate<Integer> predicate = new Predicate<Integer>(){@Overridepublic boolean test(Integer n) {return n>0;}};*/// 使用lambda表达式  判断传入的值是否大于0Predicate<Integer> predicate =(n)->{return n>0;};System.out.println(predicate.test(2));
}

执行结果:n 是一个参数传递到 Predicate 接口的 test 方法 ,如果 n> 0,则test 方法返回 true

针对断定型接口,我们还可以更简洁的lambda表达式语法:

省略()和{}:要传入的参数->判断结果

public static void main(String[] args) {Predicate<Integer> predicate = n-> n>0;System.out.println(predicate2.test(2));
}

——可以用来判断字符串是否为空,以及求奇数偶数,例如:

/*** 断定型接口:有一个输入参数,返回值只能是布尔值*/
public class PredicateDemo {public static void main(String[] args) {List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);/**  1.*  Predicate<Integer> predicate = n -> true*  n 是一个参数传递到 Predicate 接口的 test 方法*  n 如果存在则 test 方法返回 true*/System.out.println("输出全部:");eval(list, n->true);/** 2.*  Predicate<Integer> predicate1 = n -> n%2 == 0*  n 是一个参数传递到 Predicate 接口的 test 方法*  如果 n%2 为 0 test 方法返回 true*/System.out.println("输出所有偶数:");eval(list, n-> n%2 == 0 );/** 3.*  Predicate<Integer> predicate1 = n -> n > 3*  n 是一个参数传递到 Predicate 接口的 test 方法*  如果 n > 3  test 方法返回 true*/System.out.println("输出大于3 的所有数字:");eval(list, n-> n > 3 );}public static void eval(List<Integer> list, Predicate<Integer> predicate) {for(Integer n: list) {// test验证n的表达式的为true还是falseif(predicate.test(n)) {System.out.print(n + " ");}}System.out.println();}
}

执行结果:

3. Consumer (消费型接口)

只有入参,没有返回值

源码如下:

@FunctionalInterface
public interface Consumer<T> {// t 是输入参数void accept(T t);
}

具体使用:

public static void main(String[] args) {// 1.常规方式/* Consumer<String> consumer = new Consumer<String>(){@Overridepublic void accept(String str) {System.out.println(str);}};*/// 2.lambda表达式// Consumer<String> consumer = (str)-> {System.out.println(str)};// 更简洁的lambda表达式,省略()、{}Consumer<String> consumer = str-> System.out.println(str);consumer.accept("abc");
}

执行结果:消费型接口,即只消费,没有返回值

4. Supplier (供给型接口)

没有参数,只有返回值

源码如下:

@FunctionalInterface
public interface Supplier<T> {// 获得结果 T是结果的具体类型T get();
}

具体使用

public static void main(String[] args) {// 1.常规方式/* Supplier<Integer> consumer = new Supplier<Integer>(){@Overridepublic Integer get() {return 1024;}};*/// 2.lambda表达式//Supplier<Integer> supplier = ()-> {return 1024;};// 更简洁的lambda表达式,省略{}Supplier<Integer> supplier = ()-> 1024;System.out.println(supplier.get());
}

执行结果:供给型接口,顾名思义只提供,即返回结果,类似生产者

总结

函数型编程在Java8中得到大量的运用,比如Java8的新特性Stream流式计算,可参考文章:

优秀的判断力来自经验,但经验来自于错误的判断。

【Java8】函数式接口相关推荐

  1. java8函数式接口_java8的函数式接口

    函数式接口 就是在java8里允许你为一个接口(只有一个实现的,声明为FunctionalInterface注解的)实现一个匿名的对象,大叔感觉它与.net平台的委托很类似,一个方法里允许你接收一个方 ...

  2. Java8函数式接口与Lambda表达式

    摘要 何为函数式接口? 什么是lambda表达式,lambda表达式的本质: 函数式接口与lambda表达式的联系:lambda是实现函数式接口的一个快捷方式,可以作为函数式接口的一个实例: 常用Ja ...

  3. Java新特性:Java8函数式接口与Lambda表达式(一)

    摘要 何为函数式接口? 什么是lambda表达式,lambda表达式的本质: 函数式接口与lambda表达式的联系:lambda是实现函数式接口的一个快捷方式,可以作为函数式接口的一个实例: 常用Ja ...

  4. 【java8新特性】——lambda表达式与函数式接口详解(一)

    一.简介 java8于2014年发布,相比于java7,java8新增了非常多的特性,如lambda表达式.函数式接口.方法引用.默认方法.新工具(编译工具).Stream API.Date Time ...

  5. Java四大函数式接口

    Java8函数式接口 1. Consumer<T> 消费型接口 2. Supplier <R> 供给型接口 3. Function<T, R> 函数型接口 4. P ...

  6. java中的ackerman_java8的函数式接口

    函数式接口 就是在java8里允许你为一个接口(只有一个实现的,声明为FunctionalInterface注解的)实现一个匿名的对象,大叔感觉它与.net平台的委托很类似,一个方法里允许你接收一个方 ...

  7. java函数式接口意义与场景

    前言 想到记录下这篇主要是两个原因,1. 虽然自己很早就接触了函数式接口,但是基本没有深入探究过使用场景.2. 工作中接触了越来越多场景后,感觉对函数式接口有更多使用需求,能很好的美化自己代码(少写几 ...

  8. JAVA8 BiConsumer 接口

    这个接口跟<JAVA8 Consumer接口>很像,表达的想法也是一致的,都是消费的意思,我们先看下接口定义 @FunctionalInterface public interface B ...

  9. [一] java8 函数式编程入门 什么是函数式编程 函数接口概念 流和收集器基本概念...

    本文是针对于java8引入函数式编程概念以及stream流相关的一些简单介绍 什么是函数式编程?   java程序员第一反应可能会理解成类的成员方法一类的东西 此处并不是这个含义,更接近是数学上的函数 ...

  10. java compare 返回值_关于Java你不知道的那些事之Java8新特性[Lambda表达式和函数式接口]...

    前言 为什么要用Lambda表达式? Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码,将代码像数据一样传递,这样可以写出更简洁.更灵活的代码,作为一个更紧凑的代码风 ...

最新文章

  1. 如何让你的Nginx 提升10倍性能?
  2. kotlin条件表达式
  3. 小学生python-小学生都在学python
  4. 解决linux ssh客户端SSH连接linux服务器很慢的问题
  5. 机器学习笔记:Transformer
  6. 有奖竞赛 | “神策杯”高校算法大师赛揭幕,寻找最强文本处理大神
  7. ITK:创建高斯内核
  8. lesson6 字典
  9. 遇到attemp to invoke virtual method
  10. c语言给定一个非空整数数组_C程序检查给定整数的所有位是否为一(1)
  11. Java的内存模型,java初级面试笔试题
  12. 《UNIX环境高级编程(第3版)》——2.6 选项
  13. 【90】RootPort的completion timeout为什么不能阻止CPU发生MCE
  14. python 求平方根
  15. 微型计算机地址总线是16位,某微型计算机的地址总线的位数是16位,最大的寻址空间可为()。A.32KBB.64KBC.128KBD.256KB...
  16. echart图片库_附录:ECharts图属性介绍-统计图
  17. STM32_RTC晶振不起振的原因及解决方法
  18. Unity与Processing的画面传输(Spout 接收与发送)
  19. 【Vue】移动端图片裁剪组件--vue-imgcut
  20. 数据库练习(学生、课程、选课关系)

热门文章

  1. 南大通用事务型数据库GBase 8s斩获2020年中国国际金融展“金鼎奖”
  2. PHP最佳实践指南(中英对照)
  3. 什么是python的内置函数_什么是python内置函数
  4. 联想x3850x6从u盘引导,联想ThinkPad X280 BIOS设置u盘启动教程
  5. n个数输出最大值和最小值
  6. 面试篇---大四实习面试经历,总结一下自己的面试过程(函渠道、面试题、面试经验)
  7. 风暴孵化:手游代理几大优势分析
  8. 华为鸿蒙系统超级终端,华为发布鸿蒙OS Connect 打造鸿蒙硬件“超级终端”概念...
  9. ORB-SLAM3 单目地图初始化(终结篇)
  10. STM32H7系列其一