原文链接:https://blog.csdn.net/qq_29411737/article/details/80835658
jdk1.8新特性知识点:
-
Lambda表达式
- 注:当一个接口中存在多个抽象方法时,如果使用lambda表达式,并不能智能匹配对应的抽象方法,因此引入了函数式接口的概念
-
函数式接口
- 什么是函数式接口? 简单来说就是只定义了一个抽象方法的接口(Object类的public方法除外),就是函数式接口,并且还提供了注解:@FunctionalInterface
-
*注意:
* 1.lambda体中调用方法的参数列表与返回值类型,要与函数式接口中抽象方法的函数列表和返回值类型保持一致!
* 2.若lambda参数列表中的第一个参数是实例方法的调用者,而第二个参数是实例方法的参数时,可以使用ClassName::method
* -
常见的四大函数式接口
- Consumer 《T》:消费型接口,有参无返回值 con.accept(str);
- Supplier 《T》:供给型接口,无参有返回值 sup.get();
- Function 《T,R》::函数式接口,有参有返回值 fun.apply(num);
- Predicate《T》: 断言型接口,有参有返回值,返回值是boolean类型 pre.test(str);
- 在四大核心函数式接口基础上,还提供了诸如BiFunction、BinaryOperation、toIntFunction等扩展的函数式接口,都是在这四种函数式接口上扩展而来的,不做赘述。
-
总结:函数式接口的提出是为了让我们更加方便的使用lambda表达式,不需要自己再手动创建一个函数式接口,直接拿来用就好了
-
*方法引用和构造器调用
-
(a) 方法引用
三种表现形式:
1. 对象::实例方法名
2. 类::静态方法名
3. 类::实例方法名 (lambda参数列表中第一个参数是实例方法的调用 者,第二个参数是实例方法的参数时可用)(b)构造器引用
格式:ClassName::new(c)数组引用
格式:Type[]::new
-
-
Stream API
-
Stream操作的三个步骤
- 创建stream
- 中间操作(过滤、map)
- 终止操作
- 较强大的两个终止操作 reduce和collect
- reduce操作: reduce:(T identity,BinaryOperator)/reduce(BinaryOperator)-可以将流中元素反复结合起来,得到一个值;
- collect操作:Collect-将流转换为其他形式,接收一个Collection接口的实现,用于给Stream中元素做汇总的方法
-
并行流和串行流
- 在jdk1.8新的stream包中针对集合的操作也提供了并行操作流和串行操作流。并行流就是把内容切割成多个数据块,并且使用多个线程分别处理每个数据块的内容。Stream api中声明可以通过parallel()与sequential()方法在并行流和串行流之间进行切换。
jdk1.8并行流使用的是fork/join框架进行并行操作
- 在jdk1.8新的stream包中针对集合的操作也提供了并行操作流和串行操作流。并行流就是把内容切割成多个数据块,并且使用多个线程分别处理每个数据块的内容。Stream api中声明可以通过parallel()与sequential()方法在并行流和串行流之间进行切换。
-
ForkJoin框架
-
Fork/Join 框架:就是在必要的情况下,将一个大任务,进行拆分(fork)成若干个小任务(拆到不可再拆时),再将一个个的小任务运算的结果进行join 汇总。
关键字:递归分合、分而治之。
采用 “工作窃取”模式(work-stealing):
当执行新的任务时它可以将其拆分分成更小的任务执行,并将小任务加到线程队列中,然后再从一个随机线程的队列中偷一个并把它放在自己的队列中相对于一般的线程池实现,fork/join框架的优势体现在对其中包含的任务的处理方式上.在一般的线程池中,如果一个线程正在执行的任务由于某些原因无法继续运行,那么该线程会处于等待状态.而在fork/join框架实现中,如果某个子问题由于等待另外一个子问题的完成而无法继续运行.那么处理该子问题的线程会主动寻找其他尚未运行的子问题来执行.这种方式减少了线程的等待时间,提高了性能.。
-
-
Optional容器
- 使用Optional容器可以快速的定位NPE,并且在一定程度上可以减少对参数非空检验的代码量。
-
/**
* Optional.of(T t); // 创建一个Optional实例
* Optional.empty(); // 创建一个空的Optional实例
* Optional.ofNullable(T t); // 若T不为null,创建一个Optional实例,否则创建一个空实例
* isPresent(); // 判断是够包含值
* orElse(T t); //如果调用对象包含值,返回该值,否则返回T
* orElseGet(Supplier s); // 如果调用对象包含值,返回该值,否则返回s中获取的值
* map(Function f): // 如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty();
* flatMap(Function mapper);// 与map类似。返回值是Optional
*
* 总结:Optional.of(null) 会直接报NPE
*/
-
-
接口中的默认方法和静态方法
- 在接口中可以使用default和static关键字来修饰接口中定义的普通方法
-
新时间日期API
- 新的日期API LocalDate | LocalTime | LocalDateTime
新的日期API都是不可变的,更使用于多线程的使用环境中
- 新的日期API的几个优点:
-
* 之前使用的java.util.Date月份从0开始,我们一般会+1使用,很不方便,java.time.LocalDate月份和星期都改成了enum
* java.util.Date和SimpleDateFormat都不是线程安全的,而LocalDate和LocalTime和最基本的String一样,是不变类型,不但线程安全,而且不能修改。
* java.util.Date是一个“万能接口”,它包含日期、时间,还有毫秒数,更加明确需求取舍
* 新接口更好用的原因是考虑到了日期时间的操作,经常发生往前推或往后推几天的情况。用java.util.Date配合Calendar要写好多代码,而且一般的开发人员还不一定能写对。
-
- 新的日期API LocalDate | LocalTime | LocalDateTime
hashmap数据结构
(hashmap数据结构:在jdk1.8中对hashMap等map集合的数据结构优化。hashMap数据结构的优化 (知识点)
1 原来的hashMap采用的数据结构是哈希表(数组+链表),hashMap默认大小是16,一个0-15索引的数组,
2 如何往里面存储元素: 首先调用元素的hashcode 方法,计算出哈希码值,经过哈希算法算成数组的索引值,如果对应的索引处没有元素,直接存放,如果有对象在,那么比较它们的equals方法比较内容 如果内容一样,后一个value会将前一个value的值覆盖,如果不一样,在1.7的时候,后加的放在前面,形成一个链表,形成了碰撞,在某些情况下如果链表 无限下去,那么效率极低,碰撞是避免不了的
3 加载因子:0.75,数组扩容: 达到总容量的75%,就进行扩容,但是无法避免碰撞的情况发生 ;在1.8之后,在数组+链表+红黑树来实现hashmap,当碰撞的元素个数大于8时 & 总容量大于64,会有红黑树的引入 ;除了添加之后,效率都比链表高,1.8之后链表新进元素加到末尾
4 ConcurrentHashMap (锁分段机制),concurrentLevel,jdk1.8采用CAS算法(无锁算法,不再使用锁分段),数组+链表中也引入了红黑树的使用
底层数据结构: ConcurrentHashMap在jdk1.7和jdk1.8中的不同
)