JDK8的1个新特性就是支持函数式接口(Functional Interface)。

函数式接口就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。

函数式接口可以被隐式转换为Lambda表达式。

我们也可以自行定义函数式接口,如:

@FunctionalInterface
interface GreetingService{void sayMessage(String message);
}

然后通过Lambda表达式来定义接口实现(JAVA8之前一般使用匿名类来实现):

public class GreetingServiceTest {public static void main(String[] args) {GreetingService greetingService = message -> {System.out.println("Hello " + message);};greetingService.sayMessage("Mary");}
}执行返回:Hello Mary

JDK8官方也为我们定义了一些常用的函数式接口,如下图所示:


接下来,我重点介绍其中比较重要的几个函数式接口。

Function<T, R>

接收1个输入参数,返回1个结果。

  • 源码
@FunctionalInterface
public interface Function<T, R> {// 将T类型转化为R类型R apply(T t);// 先执行参数传入的Function,再执行本Functiondefault <V> Function<V, R> compose(Function<? super V, ? extends T> before) {Objects.requireNonNull(before);return (V v) -> apply(before.apply(v));}// 和compose相反,先执行本Function,再执行参数传入的Functiondefault <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {Objects.requireNonNull(after);return (T t) -> after.apply(apply(t));}// 静态方法,返回传入的泛型T自身static <T> Function<T, T> identity() {return t -> t;}
}
  • 代码示例
public class FunctionTest {public static Integer calculate(Integer i, Function<Integer, Integer> function){return function.apply(i);}public static void main(String[] args) {Function<Integer, Integer> func1 = i -> {return i+5;};Function<Integer, Integer> func2 = i -> {return i*5;};System.out.println(calculate(6, func1));System.out.println(calculate(6, func2));System.out.println(calculate(6, func1.compose(func2)));System.out.println(calculate(6, func1.andThen(func2)));System.out.println(Function.identity().apply("6+5"));}
}执行输出:11
30
35
55
6+5

Supplier

生产函数,无参数,返回1个结果。

  • 源码
@FunctionalInterface
public interface Supplier<T> {// 生产1个元素T get();
}
  • 代码示例
public class SupplierTest {public static void main(String[] args) {Supplier<String> supplier = () -> {return "商品";};System.out.println(supplier.get());}
}执行输出:商品

Consumer

消费函数,接收1个输入参数并且无返回的操作。

  • 源码
@FunctionalInterface
public interface Consumer<T> {// 消费输入tvoid accept(T t);// 先执行本接口的消费逻辑,再执行传入函数的消费逻辑default Consumer<T> andThen(Consumer<? super T> after) {Objects.requireNonNull(after);return (T t) -> { accept(t); after.accept(t); };}
}
  • 代码示例
public class ConsumerTest {public static void main(String[] args) {Consumer<String> consumer1 = s -> {System.out.println(s + ",我是消费者1");};Consumer<String> consumer2 = s -> {System.out.println(s + ",我是消费者2");};consumer1.accept("铁甲小宝");System.out.println("################");consumer1.andThen(consumer2).accept("铁甲小宝");}
}执行输出:铁甲小宝,我是消费者1
################
铁甲小宝,我是消费者1
铁甲小宝,我是消费者2

Predicate

断言函数,接受1个输入参数,返回1个布尔值结果。

  • 源码
@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);}// 取反@SuppressWarnings("unchecked")static <T> Predicate<T> not(Predicate<? super T> target) {Objects.requireNonNull(target);return (Predicate<T>)target.negate();}
}
  • 代码示例
public class PredicateTest {public static void main(String[] args) {// 断言输入值是否大于10Predicate<Integer> isSuperTen = i -> {return i>10;};System.out.println(isSuperTen.test(11));System.out.println(isSuperTen.test(6));// 取反,断言输入值是否不大于10Predicate<Integer> negate = isSuperTen.negate();System.out.println(negate.test(6));// 断言输入值是否大于20Predicate<Integer> isLowerTwenty = i -> {return i<20;};// 断言15是否>10且<20System.out.println(isSuperTen.and(isLowerTwenty).test(15));// 断言21是否>10且<20System.out.println(isSuperTen.and(isLowerTwenty).test(21));// 断言21是否>10或<20System.out.println(isSuperTen.or(isLowerTwenty).test(21));}
}执行输出:true
false
true
true
false
true

BiFunction<T, U, R>

接受1个入参T和U,并返回结果R。

  • 源码
@FunctionalInterface
public interface BiFunction<T, U, R> {// 根据输入t和u,转化为输出rR apply(T t, U u);// 先执行本函数,再执行参数传入的函数default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {Objects.requireNonNull(after);return (T t, U u) -> after.apply(apply(t, u));}
}
  • 代码示例
public class BiFunctionTest {public static void main(String[] args) {BiFunction<String, Integer, String> biFunction = (key, value) -> {return (key + ":" + String.valueOf(value));};String key = "age";Integer value = 18;System.out.println(biFunction.apply(key, value));Function<String, String> afterFunction = s -> {System.out.println("执行后继函数,添加前缀***");return "***-" + s;};System.out.println(biFunction.andThen(afterFunction).apply(key, value));}
}执行输出:age:18
执行后继函数,添加前缀***
***-age:18

BiConsumer<T, U>

代表了1个接受2个输入参数的操作,并且不返回任何结果。

  • 源码
@FunctionalInterface
public interface BiConsumer<T, U> {// 消费2个输入t和uvoid accept(T t, U u);// 先执行该函数的消费逻辑,再执行传入函数的消费逻辑default BiConsumer<T, U> andThen(BiConsumer<? super T, ? super U> after) {Objects.requireNonNull(after);return (l, r) -> {accept(l, r);after.accept(l, r);};}
  • 代码示例
public class BiConsumerTest {public static void main(String[] args) {BiConsumer<String, Integer> biConsumer1 = (s, i) -> {System.out.println("我是消费逻辑1" + "," + s + "," + String.valueOf(i+10));};BiConsumer<String, Integer> biConsumer2 = (s, i) -> {System.out.println("我是消费逻辑2" + "," + s + "," + String.valueOf(i*3));};biConsumer1.accept("铁甲小宝", 6);System.out.println("###########");biConsumer1.andThen(biConsumer2).accept("铁甲小宝", 6);}
}执行输出:我是消费逻辑1,铁甲小宝,16
###########
我是消费逻辑1,铁甲小宝,16
我是消费逻辑2,铁甲小宝,18

BiPredicate<T, U>

对2个输入参数T和U进行断言,返回1个布尔值输出。

  • 源码
@FunctionalInterface
public interface BiPredicate<T, U> {// 断言输入t和uboolean test(T t, U u);// 并操作default BiPredicate<T, U> and(BiPredicate<? super T, ? super U> other) {Objects.requireNonNull(other);return (T t, U u) -> test(t, u) && other.test(t, u);}// 取反default BiPredicate<T, U> negate() {return (T t, U u) -> !test(t, u);}// 或操作default BiPredicate<T, U> or(BiPredicate<? super T, ? super U> other) {Objects.requireNonNull(other);return (T t, U u) -> test(t, u) || other.test(t, u);}
}
  • 代码示例
public class BiPredicateTest {public static void main(String[] args) {// 判断输入1是否大于10,且输入2小于20BiPredicate<String, Integer> biPredicate = (s, i) -> {return Integer.valueOf(s) > 10 && i < 20;};System.out.println(biPredicate.test("15", 16));System.out.println(biPredicate.test("15", 21));System.out.println(biPredicate.test("6", 21));}
}执行输出:true
false
false

其他函数接口基本原理类似,不再赘述。

之所以今天讲解一下JDK8的函数式编程,主要是为后续的Flink源码解析系列做一些前置知识储备,因为Flink源码里有大量的函数式接口实践。

本文到此结束,谢谢阅读!

一文教会你JDK8的函数式编程相关推荐

  1. Jdk8新特性三:jdk8之函数式编程Function

    Jdk8新特性三:jdk8之函数式编程Function 文章目录 Jdk8新特性三:jdk8之函数式编程Function Function接口的使用 BiFunction接口解决传入两个参数问题 JD ...

  2. 一文带你了解JavaScript 函数式编程

    前言 函数式编程在前端已经成为了一个非常热门的话题.在最近几年里,我们看到非常多的应用程序代码库里大量使用着函数式编程思想. 本文将略去那些晦涩难懂的概念介绍,重点展示在 JavaScript 中到底 ...

  3. 一文带你了解JavaScript函数式编程

    摘要: 函数式编程入门. 作者:浪里行舟 Fundebug经授权转载,版权归原作者所有. 前言 函数式编程在前端已经成为了一个非常热门的话题.在最近几年里,我们看到非常多的应用程序代码库里大量使用着函 ...

  4. 一文带你了解 JavaScript 函数式编程

    (给前端大全加星标,提升前端技能) 作者:前端工匠 公号 / 浪里行舟 前言 函数式编程在前端已经成为了一个非常热门的话题.在最近几年里,我们看到非常多的应用程序代码库里大量使用着函数式编程思想. 本 ...

  5. 一文带你入门 Java 函数式编程

    Java 在最开始是不支持函数式编程的,想来也好理解,因为在 Java 中类 Class 才是第一等公民,这就导致在 Java 中实现编程不是件那么容易的事儿,不过虽然难,但是结果我们也已经知道了,在 ...

  6. SegmentFault 技术周刊 Vol.16 - 浅入浅出 JavaScript 函数式编程

    函数式编程(Functional Programming),一看这个词,简直就是学院派的典范. 以至于从 Lisp 的创世,到 Scheme.Haskell.Clean.Erlang.Miranda. ...

  7. Ruby 函数式编程

    Ruby 函数式编程 by Arnau Sanchez 本文档翻译自 Arnau Sanchez (tokland)所编译的这份文档 RubyFunctionalProgramming. 同时也有日文 ...

  8. SegmentFault 技术周刊 Vol.16 - 浅入浅出 JavaScript 函数式编程 1

    函数式编程(Functional Programming),一看这个词,简直就是学院派的典范. 以至于从 Lisp 的创世,到 Scheme.Haskell.Clean.Erlang.Miranda. ...

  9. 过程或函数的副作用是_Python函数和函数式编程(两万字长文警告!一文彻底搞定函数,建议收藏!)...

    Python函数和函数式编程 函数是可重用的程序代码段,在Python中有常用的内置函数,例如len().sum()等. 在Pyhon模块和程序中也可以自定义函数.使用函数可以提高编程效率. 1.函数 ...

最新文章

  1. ARM非对齐操作异常解决过程
  2. 三刷进博 | 跨界直播,组团参展,施耐德电气有备而来!
  3. 排队接水pascal程序
  4. 如何避免安装SQL2005的COM+错误
  5. c语言编译错误 原文,C语言常见错误与警告
  6. C++ MFC string转Cstring为什么会乱码
  7. 女神说不能每张照片P的一样,所以朋友圈开三天可见,用Python一步解决
  8. BZOJ 3626 LCA(离线+树链剖分+差分)
  9. loadrunner基础学习笔记二
  10. linux版百度导航软件,百度导航2019新版
  11. uc投屏按钮不见了_网页投屏,网页视频怎么投屏到电视,
  12. pythonturtle魔法阵_python turtle 库绘制简单魔法阵
  13. 电子设计之国赛准备-----(前言)
  14. sendgrid html text,在Node.js中的SendGrid的“发件人”字段中添加名称
  15. 前端4-2-5:关于CSS 长度单位总结,有你就够了!
  16. 阿里云centOS7安装好Nginx设置外网可以访问80端口
  17. 方队 - 启发式合并 - 主席树
  18. 全同态加密 (FHE) 框架
  19. 时间管理(番茄时钟工作法)
  20. 数字电子技术——Verilog

热门文章

  1. 从零开始做3D地图编辑器(基于QT与OGRE)
  2. HTML3天快速入门教程(详细整理附案例)
  3. 深度学习面试总结-1
  4. CV_Task3 利用ResNet实现人脸识别
  5. 21种常见大数据可视化图表
  6. html5实现像素鸟,[Swift]SpriteKit实现类似像素鸟的小游戏 - Crashy Plane
  7. java xmx4096m_为什么设置了heap最大内存为4096之后,只用了2048就内存溢出
  8. FreeNAS安装过程
  9. “对症下药”很重要——u盘数据恢复的四种方法
  10. 嘿嘿,我发现了百度网盘秒传的秘密 !!