欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java 8 实战

程序员文章站 2022-04-08 17:45:29
Java8 函数式接口,方法传递与Lambda Java8新特性 - 方法作为参数传递给方法,方法成为一等公民 - Lambda,匿名函数 - Stream API : - 函数式编程思想 - 默认方法,使接口更方便 - Opthinal避免空指针异常 ### 行为参数化 : 使代码从死板,罗嗦走向 ......

java8 函数式接口,方法传递与lambda

java8新特性

 

  • - 方法作为参数传递给方法,方法成为一等公民
  • - lambda,匿名函数
  • - stream api :
  1. 1. 将一系列相关操作用流水线的思想分配到cpu的不同内核上并行操作,而不需要费劲的使用thread实现
  2. 1. 每个流就是一系列数据项,每个流能独立的完成已有的数据向,虽然流b的数据项是由流a生产,但是不需要等待流a完成所有数据项的生产,流a会把已经完成的数据向传给流b,好让流b同时工作
  3. 1. 提倡数据分块而不是协调访问,就是说几个线程最好不要同时更新共享变量,尽量不用synchronized
  4. 1. stream的并行特性必须保证传递给流的方法没有互动(比如有可变的共享变量)
  • - 函数式编程思想
  • - 默认方法,使接口更方便
  • - opthinal避免空指针异常

### 行为参数化 : 使代码从死板,罗嗦走向灵活,简洁
- 通过颜色,重量等条件筛选苹果的例子
- 方法1:条件作为参数传递给方法,死板,罗嗦
- 方法2:通过filter接口与不同的实现类,将实现类作为参数,灵活但是罗嗦
- 方法3:通过匿名类来代替实现类,灵活但还是比较罗嗦
- 方法4:通过方法传递代替匿名类,灵活但还是有点罗嗦,但是如果方法已经存在,那这种方式就比lambda简洁
- 方法5:通过lambda表达式与函数式接口(只有一个抽象方法)代替方法传递,灵活并且简洁
- 扩展6:使用范型替代苹果,可以筛选基础类型以外的任何类型,接近完美

### java8函数式接口,方法传递与lambda
- @functionalinterface标注一个函数式接口
- 常用函数式接口
1. predicate : t -> boolean
1. 用于判断
1. test | and | or | negate
1. function : t -> r
1. apply | andthen | compose
1. consumer : t -> void
1. 消费者,用于执行操作
1. accept | andthen
1. supplier : () -> t
1. 供应商
1. get
1. compare
1. 用于比较
1. compare | comparing | reversed | thencomparing
- lambda
1. lambda是对函数式接口的简洁的实现方式
1. lambda将java这种强类型,面向对象语言变得灵活,简洁
1. 可以将lambda赋值给一个函数式接口句柄
1. 支持参数类型推断,可以省略参数类型
1. 将lambda运用于重载方法上的时候,重载方法的函数式接口的参数或者返回值不能相同,否则lambda类型检查报错
1. lambda实体内部可以使用局部变量,但是这个局部变量必须是final或者实际上是final的
1. (t t) -> u : 这个lambda描述符可以用方法已有的方法传递代替
- 神奇的例子
1. 将一个apple的list按重量排序
1. 传统做法是自己写一个冒泡算法按重量排序
1. 只对苹果list有效
1. 只对苹果重量有效
1. 需要自己实现算法
1. 通过范型使得所有list有效
1. 通过bipredicate函数接口和lambda解决重量限制
1. 再将排序算法写入list,使得算法公用
1. 通过以上我们可以对任何list按照自定义规则排序,近乎完美,但是我们仍不满足,是否能将lambda也省略?也就是将排序规则省略,只通过给出的属性按照属性自己的比较规则排序。这样做的前提是给出的属性必须实现统一接口comparable
1. lambda嵌套:当一个函数式接口的几个参数是同一个类,并且实现方法里都是调用的这个类的同一个方法时,可以嵌套使用function函数接口作为参数来构建这个函数式接口,这样做就可以使得实现方法也可以传递方法,并且可以减少参数,当然,不同类的参数也能嵌套
^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^ stream ^^^^^^^^^^^^^^^^^^
### stream 特性
1. 流操作分为中间操作和终端操作,中间操作只有在终端操作被触发时才有效,这个理念类似于构建器模式
1. 这种流水线理念的好处:可以通过循环合并,短路等技巧将中间操作合并处理,提高计算性能。
1. 流只能被消费一次

### stream类
- referencepipeline
1. maptoint(tointfunction tf) :转换为数值流
- 数值流intstream/doublestream/longstream
1. boxed() : 转换为对象流

### 创建stream
- stream.of :手动添加值
- arrays.stream(strs) :通过数组
- files.lines(path path) : 通过文件
- string.iterate(t seed, unaryoperator f) : 迭代,无限流无法排序或者归约
- stream.generate(math::random) : 生成,无限流

### 中间操作,通过一个流返回另一个流,组成流水线
- 筛选与切片
1. filter(predicate p) : 按lambda提供的条件筛选
1. distinct() : 去重
1. limit(long maxsize) : 截断
1. skip(long n) : 跳过
- 映射
1. map(function f) :获取流的特定规则的映射
1. flatmap(function f) : 扁平化流
1. maptoint(tointfunction tf) :转换为数值流
- 排序
1. sorted(comparator c) :通过指定比较器排序

### 终端操作:返回一个非流
- 查找与匹配
1. anymatch(predicate p)
1. allmatch(predicate p)
1. nonemach(predicate p)
1. findfirst() : 查找第一个
1. findany() : 查找任意一个,虽然findfirst也能实现,但是在并行流中建议使用findany
- 归约
1. reduce(t identity, binaryoperator<t> accumulator) :
1. 对所有元素进行计算得出一个结果,比如获取最大最小值
1. 与map合用便是著名的map-reduce模式
1. 三个参数的reduce方法中间的参数相当于map的功能
1. collect(collector c) : 返回一个集合, 参照collectors
1. 和reduce的区别?
- 其他
1. foreach(consumer c) : 内部循环
1. count()

^^^^^^^^^^^^^^^^^^^^^^^^^^^

^^^^^^^^^^^^^收集器^^^^^^^^^^^^^^
### collectors
- 分组
1. groupingby(function f)
1. groupingby(function f, collector c) :多极分组/分组后归约
- 归约
1. collectors.reducing(binaryoperator bo) : 所有归约都是reducing的特殊化例子
1. tolist()
1. counting()
1. maxby/minby(comparator c)
1. averagingdouble/summingdouble(todoublefunction f)
1. joining() : 连接字符串


### google guava collections
^^^^^^^^^^^^^^^^^^^^^^^^^^^

### 思考
- 接口拥有了默认方法后,抽象类的意义何在
- lambda实体内部可以使用局部变量,但是这个局部变量必须是final或者实际上是final的?
- list.sort()方法的源码分析
- 流的有状态和无状态
- reduce和collect的区别