JDK8新特性详解
JDK8主要引入了这些新特性:
- 接口的默认实现
- Lambda表达式
- 函数式接口
- 方法与构造函数引用
- 内置了许多函数式接口
- Stream流
接口的默认实现
jdk8允许我们给接口添加一个非抽象的方法实现,只需要使用default关键字接口,这个特性又叫做拓展方法。
1 2 3 4 5 6 7 8
| interface Formula { double calculate(int a);
default double sqrt(int a) { return Math.sqrt(a); } }
|
这个接口同时定义了两个方法calculate和sqrt.只不过sqrt方法拥有自己的默认实现。
Lambda表达式
在老版本中我们对一个list进行排序,我们一般需要这样写:
1 2 3 4 5 6 7 8 9
| List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
Collections.sort(names, new Comparator<String>() { @Override public int compare(String a, String b) { return b.compareTo(a); } });
|
通过JDK8之后提供的Lambda表达式,可以避免使用匿名对象,可以这样写:
1 2 3 4
| Collections.sort(names, (String a, String b) -> b.compareTo(a));
Collections.sort(names, (a, b) -> b.compareTo(a));
|
Lambda的访问外层作用域与匿名对象类类似。可以直接访问标记了final的外层局部变量或者实例的字段以及静态变量。
函数式接口
所谓的函数式接口是指有且仅有一个抽象方法的接口。
函数式接口的写法如下:
1 2 3 4
| @FunctionalInterface public interface MyFunctionalInterface { void myMethod(); }
|
函数式接口的典型使用场景就是作为方法的参数:
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class FunctionalInterface {
private static void doSomething(MyFunctionalInterface inter) { inter.myMethod(); }
public static void main(String[] args) { doSomething(() ‐> System.out.println("Lambda执行啦!")); } }
|
方法与构造函数引用
假如我们又这样一个函数式接口:
1 2 3 4 5 6
| @FunctionalInterface interface IConvert<F,T>{ T convert(F from); }
|
我们可以这样使用这个新特性:
1 2 3
| IConvert<String, Integer> convertor = (from) -> ( Integer.parseInt(from));
IConvert<String, Integer> convertor = Integer::parseInt;
|
还可以引用对象的方法;
1 2
| MyObject obj=new MyObject(); IConvert<String,String> convertor=something::startWith;
|
还可以引用构造函数
1 2 3 4
| @FunctionalInterface interface PersonFactory<P extends Person>{ P create(String firstName, String lastName); }
|
我们可以通过引用构造函数实现工厂类:
1 2
| PersonFactory<Person> factory = Person::new; Person p = factory.create("zhuge", "xx");
|
内置函数式接口
JDK8中内置了许多函数式接口,包括Comparator和Runnable等,它们被添加了@FunctionalNterface注解,以用来支持Lambda表示式。
Stream流
Stream流提供了一种对集合Collection的方便的操作。
Filter过滤
1 2 3 4 5 6 7
| List<String> list = Arrays.asList("hello","world","apple","people","sea", "watch","table","book","school","help"); list .stream() .filter(s -> s.startsWith("s")) .forEach(System.out::println);
|
Sorted排序
1 2 3 4 5
| list .stream() .sorted((a,b) -> b.compareTo(a)) .forEach(System.out::println);
|
Map
1 2 3 4 5 6 7 8 9
| List<String> list = Arrays.asList("10","100","1000");
System.out.println("---- test map ----"); list .stream() .map(Integer::valueOf) .map(a -> a + 1) .forEach(System.out::println);
|
Match匹配
这是一种终端操作,姐u共不是stream对象,而是boolean值。
1 2 3 4 5
| boolean anyMatch(Predicate<? super T> predicate); boolean allMatch(Predicate<? super T> predicate); boolean noneMatch(Predicate<? super T> predicate);
|
Count计数
这是一种终端操作,用来统计stream中元素的个数。
1 2 3 4 5 6
| long count = list .stream() .filter(s -> s.startsWith("s")) .count();
|
Reduce
list[0]和list[1]执行操作,得到的结果为result。result再和list[2]执行操作,得到的结果result。依次进行,对所有元素执行一遍.根据上述描述也可以看出,这里的“操作”必须满足两个入参、返回值是同一类型的
比如求和:
1 2 3 4 5 6 7 8 9 10
| List<Integer> list = Arrays.asList(1,2,3,4,5);
System.out.println("---- test reduce ----"); Optional<Integer> sum = list .stream() .reduce((a,b) -> a + b);
sum.ifPresent(System.out::println);
|