一篇学会Java8新特性

在这里插入图片描述

  1. 函数式接口
  2. lambda
  3. 新增方法举类
  4. Stream
  5. 接口默认方法
  6. DATE API

优点:
1.代码简洁,开发快速: 函数式编程大量使用函数,减少了代码的重复,因此程序比较短,开发速度较快
2. 接近自然语言,易于理解
3. 更方便的代码管理: 函数式编程不依赖、也不会改变外界的状态,只要给定输入参数,返回的结果必定相同
4. 易于“并发编程”:因为它不修改变量,所以根本不存在"锁"线程的问题
Lambda 表达式
Lambda 表达式将函数当成参数传递给某个方法,或者把代码本身当作数据处理;

函数式接口

函数式接口在java中是指:有且仅有一个抽象方法的接口
函数式接口,即适用于函数式编程场景的接口。而java中的函数式编程体现就是Lambda,所以函数式接口就是可以适用于Lambda使用的接口。只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利地进行推导。
如果自定义一个函数式接口尽量使用 @FunctionalInterface 函数式接口声明来说这就是一个函数式接口,别动了。
一篇学会Java8新特性_第1张图片

lambda语法格式

表达式的组成:
1.形参
2. 箭头符号 ->
3.方法体
一篇学会Java8新特性_第2张图片

自定义一个函数式接口,等下来用例子看一下它的四种语法
在这里插入图片描述
一篇学会Java8新特性_第3张图片
其中Interger::sum为方法引用,后面会讲。

注意事项

lambda 表达式只能引用标记了 final 的外层局部变量,不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。可以不使用final关键字,但是必须不可被后面的代码修改
一篇学会Java8新特性_第4张图片
编译器给的异常描述:
在这里插入图片描述

不允许声明一个与局部变量同名的参数或者局部变量
一篇学会Java8新特性_第5张图片

基本函数式接口

在实际使用中很少使用自定义函数式接口,java8中的util.function包中包含了大部分常用接口,
这些接口都是以下面四种基本函数式接口为基础的。
一篇学会Java8新特性_第6张图片一篇学会Java8新特性_第7张图片一篇学会Java8新特性_第8张图片一篇学会Java8新特性_第9张图片

新方法使用

一篇学会Java8新特性_第10张图片

foreach

API
一篇学会Java8新特性_第11张图片
源码:
源码中十一用迭代器以及四大基本类型中Consumer类型
一篇学会Java8新特性_第12张图片

使用示例
在这里插入图片描述
在这里插入图片描述

removeIf

API
一篇学会Java8新特性_第13张图片
源码
源码中是使用迭代器,去匹配每个符合条件的地址,然后去除
一篇学会Java8新特性_第14张图片
例子
在这里插入图片描述

Map中新增方法示例

foreach

API
一篇学会Java8新特性_第15张图片
源码
源码中也是使用迭代器以及Biconsumer基本函数式接口来实现的
一篇学会Java8新特性_第16张图片
这个基本函数式接口的代码:
一篇学会Java8新特性_第17张图片
例子
有两个参数,第一个参数是map的key,第二个参数是map的value;
在这里插入图片描述

还有map中一些大家常用的方法也加入到了里面,
根据key在map中获取,获取到的值为空返回默认值;
在这里插入图片描述
如果map中存在该value就不覆盖
一篇学会Java8新特性_第18张图片

根据KEY和value来判断是否删除该值
一篇学会Java8新特性_第19张图片
如果该键值对存在,替换一篇学会Java8新特性_第20张图片
根据KEY和value来判断是否替换
一篇学会Java8新特性_第21张图片

Stream

Stream类似一个高级的迭代器,单向,不可往复,数据只能遍历一遍,用户只要给出对其包涵的元素执行什么操作,Stream会隐式地在内部进行遍历做对应的操作。

特性

  • 无存储。

stream不是一种数据结构,它只是某种数据源的一个视图,数据源可以是一个数组,Java容器或I/O channel等。

  • 为函数式编程而生。

对stream的任何修改都不会修改背后的数据源,比如对stream执行过滤操作并不会删除被过滤的元素,而是会产生一个不包含被过滤元素的新stream。

  • 惰式执行。

stream上的操作并不会立即执行,只有等到用户真正需要结果的时候才会执行。

  • 可消费性。

stream只能被“消费”一次,一旦遍历过就会失效,就像容器的迭代器那样,想要再次遍历必须重新生成。

中间操作(intermediate operations)和结束操作(terminal operations),

二者特点是:
中间操作总是会惰式执行
调用中间操作只会生成一个标记了该操作的新stream,仅此而已。
结束操作会触发实际计算
计算发生时会把所有中间操作积攒的操作以pipeline的方式执行,这样可以减少迭代次数。计算完成之后stream就会失效。

      区分中间操作和结束操作最简单的方法,就是看方法的返回值,返回值为stream的大都是中间操作,否则是结束操作。

一篇学会Java8新特性_第22张图片
示例
一篇学会Java8新特性_第23张图片
一篇学会Java8新特性_第24张图片
list.stream.foreach等同于list.foreach
在这里插入图片描述
过滤和去重
在这里插入图片描述

收集器(Collector)
是为Stream.collect()方法量身打造的工具接口(类)。
考虑一下将一个Stream转换成一个容器(或者Map)需要做哪些工作?
1:目标容器是什么?是ArrayList还是HashSet,或者是个TreeMap。
2:新元素如何添加到容器中?是List.add()还是Map.put()。
3:如果并行的进行规约,还需要告诉collect() 多个部分结果如何合并成一个。
一篇学会Java8新特性_第25张图片
一篇学会Java8新特性_第26张图片

使用自带方法讲stream转为list,toList返回类型ArrayList,toSet返回类型为HashSet

一篇学会Java8新特性_第27张图片

映射

Stream背后依赖于某种数据源,数据源可以是数组、容器等,但不能是Map,
使用collect 生成Map方式
使用Collectors.toMap()生成的收集器,用户需要指定如何生成Map的key和value
使用Collectors.partitioningBy()生成的收集器,对元素进行二分区操作
使用Collectors.groupingBy()生成的收集器,对元素做group操作

一篇学会Java8新特性_第28张图片
Function.identity()返回一个输出跟输入一样的Lambda表达式对象,等价于形如t -> t形式的Lambda表达式。

使用partitioningBy()生成的收集器,这种情况适用于将Stream中的元素依据某个二值逻辑(满足条件,或不满足)
分成互补相交的两部分,比如男女性别、成绩及格与否等。下列代码展示将学生分成成绩及格或不及格的两部分。
一篇学会Java8新特性_第29张图片

map用法
在这里插入图片描述flagMap示例
在这里插入图片描述
一篇学会Java8新特性_第30张图片
map与flagMap区别
一篇学会Java8新特性_第31张图片
在执行map操作以后,我们得到是一个包含多个字符串(构成一个字符串的字符数组)的流,此时执行distinct操作是基于在这些字符串数组之间的对比,所以达不到我们希望的目的,此时的输出为:
j, a, v, a, 8] [i, s] [e, a, s, y] [t, o] [u, s, e]

一篇学会Java8新特性_第32张图片

结果正确

flatMap将由map映射得到的Stream,转换成由各个字符串数组映射成的流Stream,再将这些小的流扁平化成为一个由所有字符串构成的大流Steam,从而能够达到我们的目的。

接口的默认方法

Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做扩展方法,示例如下:
一篇学会Java8新特性_第33张图片
Formula接口在拥有calculate方法之外同时还定义了sqrt方法,实现了Formula接口的子类只需要实现一个calculate方法,默认方法sqrt将在子类上可以直接使用。
一篇学会Java8新特性_第34张图片

Date API

Java 8 在包java.time下包含了一组全新的时间日期API。新的日期API和开源的Joda-Time库差不多,但又不完全一样,下面的例子展示了这组新API里最重要的一些部分:

Clock 时钟

Clock类提供了访问当前日期和时间的方法,Clock是时区敏感的,可以用来取代 System.currentTimeMillis() 来获取当前的微秒数。某一个特定的时间点也可以使用Instant类来表示,Instant类也可以用来创建老的java.util.Date对象。
一篇学会Java8新特性_第35张图片
Timezones 时区

在新API中时区使用ZoneId来表示。时区可以很方便的使用静态方法of来获取到。 时区定义了到UTS时间的时间差,在Instant时间点对象到本地日期对象之间转换的时候是极其重要的。

一篇学会Java8新特性_第36张图片
LocalTime 本地时间

LocalTime 定义了一个没有时区信息的时间,例如 晚上10点,或者 17:30:15。下面的例子使用前面代码创建的时区创建了两个本地时间。之后比较时间并以小时和分钟为单位计算两个时间的时间差:

一篇学会Java8新特性_第37张图片
LocalTime 提供了多种工厂方法来简化对象的创建,包括解析时间字符串。

一篇学会Java8新特性_第38张图片
LocalDate 本地日期
LocalDate 表示了一个确切的日期,比如 2014-03-11。该对象值是不可变的,用起来和LocalTime基本一致。下面的例子展示了如何给Date对象加减天/月/年。另外要注意的是这些对象是不可变的,操作返回的总是一个新实例。

一篇学会Java8新特性_第39张图片
从字符串解析一个LocalDate类型和解析LocalTime一样简单:
一篇学会Java8新特性_第40张图片

LocalDateTime 本地日期时间

LocalDateTime 同时表示了时间和日期,相当于前两节内容合并到一个对象上了。LocalDateTime和LocalTime还有LocalDate一样,都是不可变的。LocalDateTime提供了一些能访问具体字段的方法。
一篇学会Java8新特性_第41张图片
只要附加上时区信息,就可以将其转换为一个时间点Instant对象,Instant时间点对象可以很容易的转换为老式的java.util.Date。

一篇学会Java8新特性_第42张图片
格式化LocalDateTime和格式化时间和日期一样的,除了使用预定义好的格式外,我们也可以自己定义格式:
一篇学会Java8新特性_第43张图片
和java.text.NumberFormat不一样的是新版的DateTimeFormatter是不可变的,所以它是线程安全的。
关于时间日期格式的详细信息:http://download.java.net/jdk8/docs/api/java/time/format/DateTimeFormatter.html

你可能感兴趣的:(Java)