Java8新特性
相比于Java7及之前,Java8中新增加的特性使得Java代码更加简洁,程序员开发更加高效,有得必有失,太过简洁的代码增加了后期阅读和维护的困难。考虑java8的语法使得java本身语法发生了很大改变,即使在开发中不使用java8,为了后面技术学习和交流,有必要熟悉java8对现有java中的影响。java8中的新特性主要包括一下几个方面[1]。
1. Lambda表达式
2. 方法引用与函数构造
3. StreamAPI
4. 接口中默认方法与静态方法
5. 其它新特性
1. Lambda表达式
1.作用
Lambda允许把函数作为一个方法参数。Java8使用函数式接口来实现Lambda,函数式接口是接口中有且只有一个抽象方法的接口[2]。
免去使用匿名内部类,当要使用一次抽象类或者接口中的方法时,为了省去实现接口或者抽象类,我们会使用到匿名内部类,当有了Lambda表达式的时候,省去了使用匿名类对接口或者抽象类中方法的重写,使得这样的场景实现起来更加方便简单[3,4]。
举例:
public class NoNameInnerClass {
@Test
public void func() {
int a = 1;
int b = 2;
//普通方式实现接口中的方法
//计算加法
MyInterface myInterface = new MyInterface() {
@Override
public int compute(int a, int b) { return a + b; }
};
System.out.println(myInterface.compute(a, b));
//计算乘法
MyInterface muti = new MyInterface() {
@Override
public int compute(int a, int b) {return a * b; }
};
System.out.println(muti.compute(a, b));
//lambda表达式调用接口中的方法
MyInterface plus = (x,y)->x+y;
System.out.println(plus.compute(a,b));
MyInterface mutis = (x,y)->{return x*y;};
System.out.println(mutis.compute(a,b));
}
}
interface MyInterface {
public int compute(int a, int b);
}
2.用法
(parameters)->expresssion或者(pamameters)->{statements;}
Lambda可以访问外部变量,但是该外部变量必须含义上是final。一种用法为使用final修饰,另外一种用法为不使用final修饰,但是一旦该局部变量在lambda使用后面就无法修改,这样对于lambda表达式来说就是语义上final的,如果lambda表达式后面尝试对该变量进行修改,则会进行报错,下面为代码示例。Lamada表达式使用外部局部变量并不是使用外部局部变量的引用而是copy外部变量的值到自己的作用域(为什么不直接使用引用,有待研究),为了避免造成混淆,规定被Lamada表达式内部使用的局部变量不能再被修改。Lamda表达式内部可以对实例变量的值进行读写,直接使用实例变量的引用。Lamda表达式内部不可以直接使用接口中定义的default方法。
int num = 1;
Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));
s.convert(2);
num = 5;
//报错信息:Local variable num defined in an enclosing scope must be final or effectively
//java: 从lambda 表达式引用的本地变量必须是最终变量或实际上的最终变量
除此之外Java8也已经定义号了一些函数式接口,常用的有以下四个,者四个函数式接口在Steam类中的函数都有使用。
1.Consumer<T>:消费性接口,在stream的forEach有使用
void accept(T t);
2.Supplier<T>:供给型接口
T accept();
3.Function<T,R>:函数式接口,在stream的map函数中有使用
R apply(T t);
4.Predicate<T>:断言型接口,在stream的filter接口中有使用
boolean test(T t);
练习:https://blog.csdn.net/huhu123444/article/details/116660194.
2. 方法引用与函数构造
方法引用是可以看成Lambda表达式的另外一种表示形式。
3. StreamAPI
1.作用
Stream主要用于数据集合(集合、数组)的处理,并生成新的元素序列。使用Stream需要主要一下三点[5]。
1) Stream自己不会存储元素。
2) Stream不会改变源对象,相反他会返回一个持有结果的新的Stream。
3) Stream是延迟操作,这意味着它们需要结果的时候才执行。
2.生成stream
第一步首先需要将数据转化为流,主要使用了Collection集合提供的stream或者parallelStream进行Stream创建;第二步为对流中数据进行操作;第三步为返回处理的结果为新的流。
接下来,当把一个数据结构包装成Stream后,就要开始对里面的元素进行各类操作了。常见的操作可以归类如下:
- Intermediate 操作
map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
- Terminal 操作
forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
- Short-circuiting 操作
anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit
4. 接口中默认方法与静态方法
Java7:只允许有常量和抽象方法,无构造器。
Java8:增加了默认方法(default)和静态方法,无构造器。
5. 其它新特性
其它的Java8新特性还有Optional容器用于预防空指针,新的时间日期API等。
Reference
[1] https://www.bilibili.com/video/BV1ut411g7E9?p=4.
[2] https://www.runoob.com/java/java8-new-features.html
[3]https://www.cnblogs.com/chenmingjun/p/8454629.html
[4] https://zhuanlan.zhihu.com/p/92687444
[5]https://www.runoob.com/java/java8-streams.html