1.Lambda表达式;
2.函数式接口;
3.方法引用和构造器引用;
4.Stream API;
5.接口中的默认方法与静态方法;
6.新时间日期API;
7.其他新特性。
1.速度更快;
2.代码更少(新增了新的语法Lambda表达式);
3.强大的Stream API;
4.便于并行;
5.最大化减少空指针异常 Optional。
其中最为核心的是Lambda表达式与Stream API.
1.Lambda表达式
为什么使用Lambda表达式
(1)Lambda是一个匿名函数,我们可以把Lambda表达式理解为一段可以传递的代码(将代码像数据一样传递)。可以写出更加简洁、灵活的代码。作为一种更加紧凑的代码风格,使java的语言表达能力得到了提升。
(2)Lambda表达式的应用
从匿名类到Lambda的转换
匿名内部类作为参数传递
2.Lambda表达式语法
Lambda表达式在Java语言中引入了一个新的语法元素和操作符。这个操作符号为"->",该操符被称为Lambda操作符 或箭头操作符。它将Lambda分为两个部分:
左侧:指定了Lambda表达式的所有参数。
右侧:制指定了Lambda体,即Lambda表达式要执行的功能。
语法格式一:无参,无返回值,Lambda体只需一条语句
语法格式二:Lambda需要一个参数
格式语法三:Lambda只有一个参数的时候,参数的小括号可以省略
格式语法四:需要两个参数,并且有返回值
格式语法五:当lambda体中只有一条语句的时候,return与大括号可以省略
格式语法六:数据类型可以省略,因为可以由编译器推断得出称为“类型判断”
类型判断:
上述Lambda表达式中的参数类型都是有编译器推断得出的。Lambda表达式中无序指定类型,程序依然可以编译,这是因为javac根据程序上下文,在后台推断出参数的类型,Lambda表达式的类型依赖于上下文环境,是由编译器推断出来的,这就是所谓的“类型推断”。
2.函数式接口
什么是函数式接口
值包含一个抽象方法的接口,称为函数式接口。
你可以通过Lambda表达式来创建该接口的对象。(若Lambda表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方法上进行声明)。
我们可以在任意函数式接口上使用@FunctionalInterface注解,这样做可以检查它是否是一个函数式接口,同事javac也会包含一条声明,说明这个接口是一个函数式接口。
自定义函数式接口
函数式接口中使用泛型:
作为参数传递的Lambda表达式:
作为参数传递的Lambda表达式:为了将Lambda表达式作为参数传递,接受Lambda表达式的参数类型必须是与该Lambda表达式兼容的函数式接口的类型。
Java内置的四大核心函数式接口
3.方法引用与构造器引用
方法引用
当要传递给Lambda体的操作,已经有实现方法了,可以使用方法引用!(实现抽象方法的列表,必须与方法引用方法的参数列表保持一致)
方法引用:使用操作符“::”将方法名和对象或类的名字分隔开来。
有如下三种情况:
对象::实例方法
类::静态方法
类::实例方法
方法引用范例:
例如:
等同于:
注意:当需要引用方法的第一个参数是调用对象,并且第二个参数是需要引用方法的第二个参数(或无参)时,ClassName::methodName
构造器引用
格式:ClassName::new
与函数式接口相结合,自动与函数式接口中方法兼容。可以把构造器引用赋值给定义的方法,与构造器参数列表要与接口中的抽象方法的参数列表一致!
数组引用
格式:type[]::new
4.强大的Stream API
了解Stream
Java8中有两大最为重要的改变。第一个是Lambda表达式;另一个就是Stream API.
Stream是Java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤映射数据等操作。使用Stream API对集合数据进行操作,就类似于使用SQL执行的数据库查询。也可以使用Stream API来并行执行操作。简而言之,Sream API提供了一种高效且易于使用的处理数据方式。
什么是Stream?
就是数据渠道,用于操作数据源(集合、数组)所产生的元素序列。“集合讲的是数据,流讲的是计算。”
注意:
1.Stream 自己不会存储元素。
2.Stream 不会改变源对象。相反,他们会返回一个持有结果的新的Stream。
3.Stream 操作时延迟执行的。这意味着他们会等到需要的结果的时候才会执行。
Stream操作的三个步骤
1.创建Stream
一个数据源(如:集合、数组),获取一个流
2.中间操作
一个中间操作链,对数据源的数据进行处理
3.终止操作(终端操作)
一个终止操作,执行中间操作链,并产生结果
1.创建Stream
Java8中的Collection接口被扩展,提供了两个获取流的方法:
default Stream
default Stream
由数组创建流
Java8中的Arrays的静态发方法stream()可以获取数组流:
String[] str=new String[16];
Stream s=Arrays.stream(str);
由值创建流
由函数创建流:创建无限流
Stream的中间操作
多个中间操作可以连接起来形成一个流水线,除非流水线上出发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性安全的全部处理,称之为“惰性求值”;
Stream的终止操作
终端操作会从流水线上生成结果。其结果可以是任何不是流的值,例如:List、Integer,甚至void。
备注:map和reduce的链接通常称为map-reduce模式,因Google用它来进行网络搜索而出名。
Collector接口中方法的实现决定了如何对流执行收集操作(如收集到List、Set、Map)。但是Collectors实用类提供了很多静态方法,可以方便地创建常见收集器实例,具体方法与实例如下表:
并行流与串行流
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。
Java8中将并行进行了优化,我们可以很容易的对数据进行并行操作。Stream API可以声明性的通过parallel()与sequential()在并行流与顺序流之间进行切换。
5.新时间日期API
后续补充
6.接口中的默认方法与静态方法
Java8 中允许接口中包含具有具体实现的方法,该方法称为“默认方法”,默认方法使用default关键字修饰。
例如:
接口中的默认方法
接口中的默认方法的“类优先”原则
若一个接口中定义了一个默认方法,而另外一个父类或接口中又定义了一个同名的方法时:
1.选择父类中的方法。如果一个父类提供了具体的实现,那么接口中具有相同名称和参数的默认方法会被忽略。
2.接口冲突。如果一个父接口提供一个默认方法,而另一个接口也提供了一个具有相同名称和参数列表的方法(不管方法是否是默认方法),那么必须覆盖该方法解决冲突。
接口中的静态方法
Java8中,接口中允许添加静态方法。
7.其他新特性
Optional类
Optional
常用方法:
Optional.of(T t) : 创建一个Optional实例;
Optional.empty() : 创建一个空的Optional实例;
Optional.ofNullable(T t) :若t不为空创建一个Optional实例否则创建一个空实例;
isPresent() : 判断是否包含值;
orElse(T t) :如果调用对象包含值,返回该值,否则返回t;
orElseGet(Supplier s) : 如果调用对象包含值,返回该值,否则返回s获取的值;
map(Function f) : 如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty();
flatMap(Function mapper) : 与map类似,要求返回值必须是Optional。