一、Lambda表达式
百度百科定义:
Lambda 表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。
Lambda 表达式表达式有三部分组成:参数列表,箭头(->),以及一个表达式或语句块。Lambda表达式有利于函数式编程,简化了开发了很多。
lambda表达式的重要特征:
- 可选类型声明 - 无需声明参数的类型。编译器可以从该参数的值推断。
- 可选圆括号参数 - 无需在括号中声明参数。对于多个参数,括号是必需的。
- 可选大括号 - 表达式主体没有必要使用大括号,如果主体中含有一个单独的语句。
- 可选return关键字 - 编译器会自动返回值,如果主体有一个表达式返回的值。花括号是必需的,以表明表达式返回一个值。
总结:
- lambda表达式主要用于定义内联执行的功能的接口,即只有一个单一的方法接口。Java8定义被广泛应用于lambda表达式很多函数形式的接口。以下是在java.util.Function包中定义的功能接口列表。
- Lambda表达式消除匿名类的需求,并给出了一个非常简单但功能强大的函数式编程能力。函数式编程扫盲
变量的作用域
总结:
在lambda表达式,可以指任何最终的变量或有效的最后一个变量(被分配一次)。
二、接口的默认方法和静态方法
java 8版之前,接口只有抽象方法,而在Java 8,为接口新增了两种类型的方法。
结论:
- 第一种是默认方法。此方法使用了default关键字修饰方法名。实际上接口不包含任何实现的方法,而在Java 8中,可以通过使用default关键字来添加默认的方法实现。
- 这一点与类中的静态方法相似,可以在接口中使用static关键字定义静态方法。如果我们要调用接口定义的静态方法,只需使用接口名就可以访问这些静态方法。
三、JAVA 8 Stream
流代表从支持聚合操作源的序列的对象。以下是数据流的特点。
- 元素序列 - 流提供了一组特定类型的以顺序方式元素。流获取/计算需求的元素。它不存储元素。
- 源- 流使用集合,数组或I/O资源为输入源。
- 聚合操作 - 数据流支持如filter, map, limit, reduced, find, match等聚合操作。
- 管道传输 - 大多数流操作的返回流本身使他们的结果可以被管道传输。这些操作被称为中间操作以及它们的功能是利用输入,处理输入和输出返回到目标。collect()方法是终端操作,这是通常出现在管道传输操作结束标记流的结束。
- 自动迭代 - 流操作内部做了反复对比,其中明确迭代需要集合提供源元素。
创建Stream
方法
|
用法
|
例子
|
备注
|
---|---|---|---|
Collection子类获取Stream | Collection子类.stream() | List list = new ArrayList(); list.stream(); | |
Stream接口的generator静态方法,生成一个无限长度的Stream | Stream.generate() | Stream.generate(() -> Math.random()); Stream.generate(Math::random); | 创建无穷stream |
Stream接口的of静态方法 | Stream.of() | Stream<Integer> integerStream = Stream.of( 1 , 2 , 3 , 5 ); |
Stream常用操作
ForEach
ForEach:数据流提供了新的forEach方法遍历该流中的每个元素
map
map:map 方法用于映射每个元素对应的结果
filter
filter:filter方法用于消除基于标准元素
limit
limit:方法用于减少流的大小
sorted
sorted:用来流排序
collect
collect:收集器是用来处理组合在一个数据流的元素的结果。收集器可用于返回一个列表或一个字符串。
统计
summaryStatistics:使用Java8,统计收集器引入计算所有统计数据时,流处理可以做这些。
四、Optional类
Optional用于包含非空对象的容器对象。Optional对象,用于表示使用不存在null值。这个类有各种实用的方法,以方便代码来处理为可用或不可用,而不是检查null值。它是Java引入, 是类似于在 Guava 中的 Optional 。
五、日期时间API扩展
使用Java8,新的日期时间API引入覆盖旧的日期时间API的以下缺点。
- 非线程安全 - java.util.Date不是线程安全的,因此开发者必须在使用日期处理并发性问题。新的日期时间API是不可变的,并且没有setter方法。
- 设计不佳 - 默认的开始日期从1900年,开始每月从1天从0开始,所以没有统一。不直接使用方法操作日期。新的API提供了这样操作实用方法。
- 困难的时区处理 - 开发人员必须编写大量的代码来处理时区的问题。新的API设计开发保持特定领域设计。
JAVA8引入了java.time包 - 下一个新的日期时间API。以下是一些在java.time程序包引入重要的类。【与joda-time用法相似】
- 本地 - 简化日期时间API,没有时间处理区的复杂性。
-
时区 - 专业的日期时间API来处理各种时区。
六、并行、并发
并行(parallel)数组
Java 8增加了大量的新方法来对数组进行并行处理。可以说,最重要的是parallelSort()方法,因为它可以在多核机器上极大提高数组排序的速度。
并发(Concurrency)
在新增Stream机制与lambda的基础之上,在java.util.concurrent.ConcurrentHashMap中加入了一些新方法来支持聚集操作。同时也在java.util.concurrent.ForkJoinPool类中加入了一些新方法来支持共有资源池(common pool)。
改进一:取消segments字段,直接采用transient volatile HashEntry<K,V>[] table保存数据,采用table数组元素作为锁,从而实现了对每一行数据进行加锁,进一步减少并发冲突的概率。
改进二:将原先table数组+单向链表的数据结构,变更为table数组+单向链表+红黑树的结构。对于个数超过8(默认值)的列表,jdk1.8中采用了红黑树的结构改进性能。
七、JAVA 8内存划分
JDK8中HotSpot JVM不再有PermGen,类的元数据信息(metadata)还在,只不过不再是存储在连续的堆空间上,而是移动到叫做“Metaspace”的本地内存(Native memory)中。
元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制,但可以通过以下参数来指定元空间的大小:链接
-XX:MetaspaceSize,初始空间大小,达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize时,适当提高该值。
-XX:MaxMetaspaceSize,最大空间,默认是没有限制的。
除了上面两个指定大小的选项以外,还有两个与 GC 相关的属性:
-XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾收集
-XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空间容量的百分比,减少为释放空间所导致的垃圾收集
使用元空间的几点原因:
1、字符串存在永久代中,容易出现性能问题和内存溢出。
2、类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出。
3、永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。
4、Oracle 可能会将HotSpot 与 JRockit 合二为一。
科普(小道消息)链接:
JDK8 HotSpot JVM 使用本地内存来存储类元数据信息并称之为:元空间(Metaspace),这与Oracle JRockit 和IBM JVM’s很相似。由于类的元数据可以在本地内存(native memory)之外分配,所以其最大可利用空间是整个系统内存的可用空间。这样,你将不再会遇到OOM错误,溢出的内存会涌入到交换空间。这个新特性也不能神奇地消除类和类加载器导致的内存泄漏。