JAVA8 新特性总结(LocalDateTime、Lamada、Stream)

LocalDateTime用法
1.LocalDateTime用法与简介
2.新时间日期API常用、重要对象介绍
ZoneId: 时区ID,用来确定Instant和LocalDateTime互相转换的规则
Instant: 用来表示时间线上的一个点(瞬时)
LocalDate: 表示没有时区的日期, LocalDate是不可变并且线程安全的
LocalTime: 表示没有时区的时间, LocalTime是不可变并且线程安全的
LocalDateTime: 表示没有时区的日期时间, LocalDateTime是不可变并且线程安全的
Clock: 用于访问当前时刻、日期、时间,用到时区
Duration: 用秒和纳秒表示时间的数量(长短),用于计算两个日期的“时间”间隔
1.8-Period: 用于计算两个“日期”间隔
2.时间对象
LocalDate : 只含年月日的日期对象 LocalTime :只含时分秒的时间对象 LocalDateTime : 同时含有年月日时分秒的日期对象

在这里插入图片描述
Lamada表达式
1.Lamada表达式介绍与入门
2.1什么是Lambda表达式
带有参数变量的表达式,是一段可以传递的代码,可以被一次或多次执行
是一种精简的字面写法,其实就是把匿名内部类中“一定”要做的工作省略掉
然后由JVM通过推导把简化的表达式还原
格式: (parameters参数) -> expression表达式或方法体
paramaters:
类似方法中的形参列表,这里的参数是函数式接口里的参数
->:可理解为“被用于”的意思
方法体:
可以是表达式也可以代码块,是函数式接口里方法的实现
如果负责运算的代码无法用表达式表示,可以使用编写方法实现
但必须用{}包围并按需明确使用 return语句
2.1 Lamada的作用
需要显示创建函数式接口对象的地方,都可以使用
实际上函数式接口的转换是Lambda表达式唯一能做的事情
即lambda必须和Functional Interface配套使用
2.2 .函数式接口分类
a.系统与定义函数接口(Comparator, Runnable)
b.用户自定义函数接口(注解必须有,表达式是直接通过参数列表来实现的,只能有一个有效方法)
2.3.公共定义的函数式接口
最为核心的有四个接口:
a.功能性接口:Function<T, R>(有输入参数,有返回值
是对接收一个T类型参数,返回R类型的结果的方法的抽象)
b.消费型接口:Consumer有输入参数,没返回值
对应的方法类型为接收一个参数,没有返回值
一般来说使用Consumer接口往往伴随着一些期望状态的改变
或者事件的发生,典型的forEach就是使用的Consumer接口
虽然没有任何的返回值,但是向控制台输出结果
Consumer 使用accept对参数执行行为
c.供给型接口:Supplier无传入参数,有返回值
该接口对应的方法类型不接受参数,但是提供一个返回值
使用get()方法获得这个返回值
d.断言型接口:Predicate有传入参数,有返回值Boolean
该接口对应的方法为接收一个参数,返回一个Boolean类型值
多用于判断与过滤,使用test()方法执行这段行为
2.4Lambda的优点
a.极大的减少代码冗余,同时可读性也好过冗长的匿名内部类
b.与集合类批处理操作结合,实现内部迭代,并充分利用现代多核CPU进行并行计算。之前集合类的迭代都是外部的,即客户代码。而内部迭代意味着由Java 类库来进行迭代,而不是客户代码
2.5和匿名内部类的区别
a.在lambda中,this不是指向lambda表达式产生的那个对象,而是它的外部对象
b.Java 编译器编译 Lambda 表达式并将他们转化为类里面的私有函数,它使用 Java 7 中新加的 invokedynamic 指令动态绑定该方法,但每一个匿名内部类编译器会为其创建一个类文件
Stream流
3.1Stream好处:
a.代码冗余
b.实现并行计算很麻烦
c.代码无法及时传递程序员的意图 ,必须读完代码
3.2原理:
a. 外部迭代(forEach工作原理:代码底层使用Iterator进行迭代的,是串行化操作)
在这里插入图片描述
b.内部迭代
在这里插入图片描述
常用操作
a.forEach
迭代集合中元素。接收一个 Lambda 表达式
然后在 Stream 的每一个元素上执行该表达式
此操作是及早求值方法
b.collect(toList())
由Stream 里的值生成一个列表,是一个及早求值操作
很多Stream 操作都是惰性求值,因此调用Stream 一系列方法之后
还需最后再调用一个类似collect 的及早求值方法返回集合
使用filter过滤器:遍历数据并检查其中的元素
map
如果有一个函数可以将一种类型的值转换成另外一种类型
map 操作就可以使用该函数,将一个流中的值转换成一个新的流
需求:将字符串全转换成大写
filter
遍历数据并检查其中的元素。例如获取字符串List中以数字开始的字符集合
.flatMap
可用Stream 替换值, 然后将多个Stream 连接成一个Stream
map 操作可用一个新的值代替Stream 中的值
若用户希望让map操作有点变化
生成一个新的Stream 对象取而代之则flatMap适用
假设有一个包含多个列表的流,现在希望得到所有数字的序列
max和min
获取Stream中最大值或最小值,获取字符串List中长度最长的字符串长度
reduce
通过指定的函数把stream中的多个元素汇聚为一个元素,min max等是它的特例,格式:reduce(初始值,(r, i) -> r + i) 或者 reduce((r, i) -> r + “*” i)
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
并行API
1.概述
在Java7之前,并行处理数据基本是通过多线程来解决
a.将数据分成部分
b.给每个子部分分配一个子线程
c.等待所有的子线程全部结束
d.合并子线程
这样的并行数据处理不稳定、易出错,在Java8中Stream接口应用分支/合并框架
将一个数据内容分成多个数据块,并用不同的线程分别处理每个数据块流
Stream有串行和并行两种,串行Stream上的操作是在一个线程中依次完成
而并行Stream则是在多个线程上同时执行
并行是每个cpu运行一个程序
2.使用方法
通常编写并行代码很难而且容易出错,
但使用 Stream API 无需编写一行多线程的代码
就可以很方便地写出高性能的并发程序
a.调用Stream的parallel()方法
b.调用Collection的parallelStream()方法
c.parallel() 与 sequential() 可在并行流与顺序流之间切换
3.使用并行的建议
a.尽量使用基本类型的流 IntStream, LongStream, and DoubleStream
b.有些操作使用并发流的性能会比顺序流的性能更差,比如limit,findFirst,依赖元素顺序的操作在并发流中是极其消耗性能的.findAny的性能就会好很多,因为不依赖顺序
c.考虑流中计算的性能(Q)和操作的性能(N)的对比, Q表示单个处理所需的时间, N表示需要处理的数量,如果Q的值越大, 使用并发流的性能就会越高
d.数据量不大时使用并发流,性能得不到提升
e.考虑数据结构:并发流需要对数据进行分解,不同的数据结构被分解的性能时不一样的
f.传递给并行流的函数都是线程安全的,无副作用
4.何时需要并行编程
a.是否需要并行
弄清楚你要解决的问题是什么,数据量有多大,计算的特点是什么
并不是所有的问题都适合使用并发,比如当数据量不大时
顺序执行往往比并行执行更快。
准备线程池和其它相关资源也是需要时间的
但当任务涉及到I/O操作并且任务之间不互相依赖时,那么适合并行化
b.任务之间是否是独立的?是否会引起任何竞态条件
如果任务之间是独立的
并且代码中不涉及到对同一个对象的某个状态或者某个变量的更新操作

那么就表明代码是可以被并行化的
c.结果是否取决于任务的调用顺序
由于在并行环境中任务的执行顺序是不确定的
因此对于依赖于顺序的任务而言,并行化也许不能给出正确的结果

猜你喜欢

转载自blog.csdn.net/qq_44293888/article/details/103010503