核心概念

Java8是怎么支持函数编程的呢?主要有三个核心概念:

  • 函数接口(Function)
  • 流(Stream)
  • 聚合器(Collector)

函数接口

关于函数接口,需要记住的就是两件事:

  • 函数接口是行为的抽象;

  • 函数接口是数据转换器。

最直接的支持就是 java.util.Function 包。定义了四个最基础的函数接口:

  • Supplier<T>: 数据提供器,可以提供 T 类型对象;无参的构造器,提供了 get 方法;
  • Function<T,R>: 数据转换器,接收一个 T 类型的对象,返回一个 R类型的对象; 单参数单返回值的行为接口;提供了 apply, compose, andThen, identity 方法;
  • Consumer<T>: 数据消费器, 接收一个 T类型的对象,无返回值,通常用于设置T对象的值; 单参数无返回值的行为接口;提供了 accept, andThen 方法;
  • Predicate<T>: 条件测试器,接收一个 T 类型的对象,返回布尔值,通常用于传递条件函数; 单参数布尔值的条件性接口。提供了 test (条件测试) , and-or- negate(与或非) 方法。

其中, compose, andThen, and, or, negate 用来组合函数接口而得到更强大的函数接口。

其它的函数接口都是通过这四个扩展而来。

  • 在参数个数上扩展: 比如接收双参数的,有 Bi 前缀, 比如 BiConsumer<T,U>, BiFunction<T,U,R> ;
  • 在类型上扩展: 比如接收原子类型参数的,有 [Int|Double|Long][Function|Consumer|Supplier|Predicate]
  • 特殊常用的变形: 比如 BinaryOperator , 是同类型的双参数 BiFunction<T,T,T> ,二元操作符 ; UnaryOperator 是 Function<T,T> 一元操作符。

java.util.Function中函数接口整理参考:java.util.function包

聚合器

每一个流式计算的末尾总有一个类似 collect(Collectors.toList()) 的方法调用。collect 是 Stream 的方法,而参数则是聚合器Collector。已有的聚合器定义在Collectors 的静态方法里。 那么这个聚合器是怎么实现的呢?

Reduce

大部分聚合器都是基于 Reduce 操作实现的。 Reduce ,名曰推导,含有三个要素: 初始值 init, 二元操作符 BinaryOperator, 以及一个用于聚合结果的数据源S。

Reduce 的算法如下:

  1. STEP1: 初始化结果 R = init ;
  2. STEP2: 每次从 S 中取出一个值 v,通过二元操作符施加到 R 和 v ,产生一个新值赋给 R = BinaryOperator(R, v);重复 STEP2, 直到 S 中没有值可取为止。

比如一个列表求和,Sum([1,2,3]) , 那么定义一个初始值 0 以及一个二元加法操作 BO = a + b ,通过三步完成 Reduce 操作:step1: R = 0; step2: v=1, R = 0+v = 1; step2: v=2, R = 1 + v = 3 ; step3: v = 3, R = 3 + v = 6。

四要素

一个聚合器的实现,通常需要提供四要素:

  • 一个结果容器的初始值提供器 supplier
  • 一个用于将每次二元操作的中间结果与结果容器的值进行操作并重新设置结果容器的累积器 accumulator
  • 一个用于对Stream元素和中间结果进行操作的二元操作符 combiner
  • 一个用于对结果容器进行最终聚合的转换器 finisher(可选) 。

流(Stream)是Java8对函数式编程的重要支撑。大部分函数式工具都围绕Stream展开。

Stream的接口

Stream 主要有四类接口:

  • 流到流之间的转换:比如 filter(过滤), map(映射转换), mapTo[Int|Long|Double] (到原子类型流的转换), flatMap(高维结构平铺),flatMapTo[Int|Long|Double], sorted(排序),distinct(不重复值),peek(执行某种操作,流不变,可用于调试),limit(限制到指定元素数量), skip(跳过若干元素) ;
  • 流到终值的转换: 比如 toArray(转为数组),reduce(推导结果),collect(聚合结果),min(最小值), max(最大值), count (元素个数), anyMatch (任一匹配), allMatch(所有都匹配), noneMatch(一个都不匹配), findFirst(选择首元素),findAny(任选一元素) ;
  • 直接遍历: forEach (不保序遍历,比如并行流), forEachOrdered(保序遍历) ;
  • 构造流: empty (构造空流),of (单个元素的流及多元素顺序流),iterate (无限长度的有序顺序流),generate (将数据提供器转换成无限非有序的顺序流), concat (流的连接), Builder (用于构造流的Builder对象)

除了 Stream 本身自带的生成Stream 的方法,数组和容器及StreamSupport都有转换为流的方法。比如 Arrays.stream , [List|Set|Collection].[stream|parallelStream] , StreamSupport.[int|long|double|]stream;

流的类型主要有:Reference(对象流), IntStream (int元素流), LongStream (long元素流), Double (double元素流) ,定义在类 StreamShape 中,主要将操作适配于类型系统。

Reference流相关类

Java8函数式编程(1)--Principle相关推荐

  1. [2017.02.23] Java8 函数式编程

    以前学过Haskell,前几天又复习了其中的部分内容. 函数式编程与命令式编程有着不一样的地方,函数式编程中函数是第一等公民,通过使用少量的几个数据结构如list.map.set,以及在这些数据结构上 ...

  2. java8 函数式编程_如何使用Java 8函数式编程生成字母序列

    java8 函数式编程 我偶然发现了用户" mip"一个有趣的堆栈溢出问题 . 问题是: 我正在寻找一种生成字母序列的方法: A, B, C, ..., Z, AA, AB, AC ...

  3. java8 函数式编程_使用Javaslang进行Java 8中的函数式编程

    java8 函数式编程 我们非常高兴地在jOOQ博客上宣布一个客座帖子,该帖子由HSH Nordbank的高级软件工程师Daniel Dietrich (三人的丈夫和父亲)撰写. 他目前作为项目负责人 ...

  4. java8 函数式编程_Java 8函数式编程:延迟实例化

    java8 函数式编程 单例通常会延迟实例化自己,有时,如果对象足够重,则可以延迟实例化类字段. 通常,在走惰性路线时,getter方法(或accessor )必须具有一段代码,该代码块在返回对象之前 ...

  5. java8 函数式编程_您必须学习Java 8的函数式编程吗?

    java8 函数式编程 我最近一直在研究Java 8,并掌握了Manning出版的" Java 8 In Action" . 让我印象深刻的第一件事是Java 8独特的销售主张是函 ...

  6. Java8函数式编程详解

    Java8 函数式编程详解 Author:Dorae Date:2017年11月1日23:03:26 转载请注明出处 说起Java8,可能很多人都已经知道其最大的改进,就是引入了Lambda表达式与S ...

  7. Java8函数式编程_8--设计和架构的原则

    1,免责声明,本文大部分内容摘自<Java8函数式编程>.在这本书的基础上,根据自己的理解和网上一些博文,精简或者修改.本次分享的内容,只用于技术分享,不作为任何商业用途.当然这本书是非常 ...

  8. Java8函数式编程语法入门

    Java8函数式编程语法入门 Java8中函数式编程语法能够精简代码. 使用Consumer作为示例,它是一个函数式接口,包含一个抽象方法accept,这个方法只有输入而无输出. 现在我们要定义一个C ...

  9. Java8函数式编程_9--使用Lambda表达式编写并发程序

    1,免责声明,本文大部分内容摘自<Java8函数式编程>.在这本书的基础上,根据自己的理解和网上一些博文,精简或者修改.本次分享的内容,只用于技术分享,不作为任何商业用途.当然这本书是非常 ...

最新文章

  1. three.js 一个页面可以存在多个render吗_你确定把Spring MVC的视图机制吃透了吗?...
  2. Java黑皮书课后题第6章:*6.38(生成随机字符)使用程序清单6-10 RandomCharacter中的方法,打印100个大写字母及100个一位数字,每行打印10个
  3. python中的set方法_Python中set与frozenset方法和区别详解
  4. creator qt 字体太小_qt ttf 字体太小的解决方法
  5. [新思路]Online DVD Rental! 美国在线DVD租赁
  6. FFMPEG基于内存的转码实例
  7. Hello log4net——做一个实用好用的log4net的demo(转)
  8. 9、包、访问控制、import、static、static代码块、final、抽象类、接口、instanceof、多态...
  9. 日常一些需要搜索,需要花功夫但又简单的东西 此文会持续更新
  10. 性能测试--jmeter中HTTP Cookie管理器的使用【18】
  11. java编程对电脑配置_java编程对电脑配置有什么要求?如何选择合适电脑?
  12. 计算机业打字排版比赛计算机实施方案,大学“新生杯”计算机打字比赛活动策划书...
  13. 开放报名 | “2021 年全国人工智能大赛”正式开赛
  14. 云更新网吧系统服务器,云更新网吧无盘
  15. Centos 安装SVN
  16. Pareto最优解 Pareto分布
  17. Linux openssl 生成证书的详解
  18. Flash数据读取和保存
  19. HDMI差分对走线是否需要走等长
  20. 基于STL的演讲比赛流程管理系统

热门文章

  1. 【Hibernate】hibernate主键生成策略与配置详解
  2. 福州大学软工 1715 | K 班 - 启航
  3. springmvc中的全注解模式
  4. iOS开发Swift篇—(六)流程控制
  5. Activity的启动模式详解
  6. Horizon View 6-客户端连接虚拟桌面⑹
  7. 微软发布Win 10 开始按钮真正回归明年底上市
  8. Listary-不仅仅是快速检索文件
  9. java在文本区输出方法_Java文件的几种读取、输出方式
  10. visio2013跨线问题