JDK8新特性
最近看视频总结了一些JDK8新特性,做个笔记来和大家一起分享一下,加*为重点哦~
•接口的默认方法
允许在interface中实现方法,只需要添加 default 关键字,这个特征又叫扩展方法。
•Lambda表达式*
可以取代大部分的匿名内部类,在集合的遍历和其他集合操作中,可以极大地优化代码结构。
List<String> names = Arrays.asList("peter","anna","mike","alice");
//JDK8之前 采用匿名内部类
Collections.sort(names, new Comparator<String>(){
@Override
public int compare(String a, String b){
return b.compareTo(a);
}
});
//JDK8之后 使用lambda表达式
Collections.sort(names, (String a, String b) -> {
return b.compareTo(a);
});
//简写形式
Collections.sort(names, (String a, String b) -> b.compareTo(a));
Collections.sort(names, (a, b) -> b.compareTo(a));
前置 | 语法 |
---|---|
无参数无返回值 | () -> System.out.println(“Hello World”) |
有一个参数无返回值 | (x) -> System.out.println(x) |
有且只有一个参数无返回值 | x -> System.out.println(x) |
有多个参数,有返回值,有多条lambda体语句 | (x, y) -> {System.out.println(“xxx”);return xxx;} |
有多个参数,有返回值,只有一条lambda体语 | (x, y) -> xxxx |
•函数式接口*
只定义了一个抽象方法的接口,就是函数式接口,并且还要提供注解@FunctionalInterface。
四大函数式接口
函数式接口 | 参数类型 | 返回类型 | 用途 |
---|---|---|---|
Consumer 消费型接口 | T | void | 对类型为T的对象应用操作,包含方法:void accept(T t); |
Supplier 供给型接口 | 无 | T | 返回类型为T的对象,包含方法:T get(); |
Function<T,R> 函数型接口 | T | R | 对类型为T的对象应用操作,并返回结果。结果是R类型的对象。包含方法:R apply(T t); |
Predicate 断言型接口 | T | boolean | 确定类型为T的对象是否满足某约束,并返回boolean值。包含方法:boolean test(T t); |
//自定义函数式接口
@FunctionalInterface
interface Converter<F, T>{
T convert(F from);
}
Converter<String, Integer> converter = (from) -> Integer.valueOf(from);
Integer converted = converter.convert("123");
System.out.println(converted);
//四大函数式接口之函数型接口举例
Function<String, Integer> function1 = o -> Integer.parseInt(o);
Integer integer = function1.apply("123");
•方法引用、构造器引用以及数组引用
-
方法引用
当要传递给lambda体的操作已经有实现的方法了,可以使用方法引用。
方法引用:使用操作符"::"将方法名和对象或类的名字分隔开来。如以下三种主要使用情况:
对象::实例方法 Consumer con = System.out::println;
类::静态方法 Comparator com = Integer::compare;
类::实例方法 BiPredicate<String, String> biPredicate = String::equals; -
构造器引用
格式:ClassName::new
与函数式接口相结合,自动与函数式接口中方法兼容。可以把构造器引用赋值给定义的方法,构造器参数列表要与接口中抽象方法的参数列表一致。
Function<Integer, Integer[]> fun1 = MyClass::new;
fun1.apply(args…); -
数组引用
格式:type[]::new
Function<Integer, Integer[]> fun = n -> new Integer[n];
Function<Intefer, Intefer[]> fun1 = Integer[]::new
fun1.apply(10);
•Stram API*
java.util.Stream接口是对集合功能的增强,可以对集合元素进行复杂的查找、过滤、筛选等操作。
Stream接口借助于Lambda表达式极大的提高编程效率和程序可读性,同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势。
注意: ①Stream不会存储元素; ②Stream不会改变源对象,相反,会返回一个持有结果的新Stream; ③Stream操作是延迟执行的,即会等到需要结果的时候才执行。
Stream操作的三个步骤:
1.创建Stream(一个数据源,如集合、数组,获取一个流)
方式一:通过调用集合的默认方法来获取流,如:default Stream stream()
方式二:通过数组工具类中的静态方法来获取流,如:static IntStream stream(int[] array)
方式三:通过Stream接口的静态方法来获取流,如:static Stream of(T... values)
方式四:通过Stream接口的静态方法来获取流,static Stream generate(Supplier <? extends T>)
2.中间操作(即对数据源进行一系列的操作处理,产生新的Stream)
筛选和切片:
I.filter(predicate)-接收lambda,从流中排除某些元素;
II.limit(n)-截断流,使其元素不超过给定数量;
III.skip(n)-跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补;
IV.distinct-筛选,通过流所生成元素的hashcode()和equals()去重复元素。
映射:
I.map-如果需要将流中的元素映射到另一个流中,可以使用map方法;
II.flatMap-实现流的合并。
排序:
I.sorted()-产生一个新流,其中按自然顺序排序;
II.sorted(Comparator)-产生一个新流,其中按比较器顺序排序。
3.终止操作(产生结果)
a.allMatch-检查是否匹配所有元素;
b.anyMatch-检查是否至少匹配一个元素;
c.noneMatch-检查是否没有匹配所有元素;
d.findFirst-返回流中第一个元素;
e.findAny-返回当前流中的任意元素;
f.count-返回流中元素的总数;
g.max-返回流中最大值;
h.min-返回流中最小值;
i.forEach(Consumer c)-内部迭代。
public static void main(String[] args){
List<Person> list = new ArrayList<>[];
list.add(new Person("zhangfei",30));
list.add(new Person("xiaoqiao",17));
list.add(new Person("zhouyu",20));
list.add(new Person("liubei",40));
list.stream().skip(1).limit(2).forEach(System.out::println);
}
•新的日期API
LocalDate、LocalTime、LocalDateTime都是线程安全的,更适用于多线程的使用环境中。
•Optional容器
方法声明 | 功能介绍 |
---|---|
static Optional ofNullable(T value) | 根据参数指定数值来得到Optional类型的对象 |
Optional map(Function<? super T,? extends U> mapper) | 根据参数指定规则的结果来得到Optional类型的对象 |
T orElse(T other) | 若该值存在就返回,否则返回other的数值 |
java.util.Optional类可以理解为一个简单的容器,其值可能是null或者不是null,代表一个值存在或不存在。
该类的引入很好的解决了空指针异常,不用现实进行空值检测。
public static void main(String[] args){
String str = null;
//1、将字符串str装到Optional对象代表的容器中
Optional<String> optiponal = Optional.ofNullable(str);
//2、建立映射关系 使字符串的长度和字符串建立映射关系
Optional<Integer> integer = optional.map(String::length);
//3、打印结果 若字符串为空则打印0,否则打印字符串的数值
System.out.println(integer.orElse(0));
}
•Annotation注解
重复注解:即允许在同一申明类型(类,属性,或方法)前多次使用同一个类型注解。Java8允许我们把同一个类型的注解使用多次,只需要给该注解标注一下@Repeatable即可。
类型注解:在Java8以前,注解只能用在各种程序元素(定义类、定义接口、定义方法、定义成员变量…)上。从Java8开始,类型注解可以用在任何使用到类型的地方,并且ElementType中多了两个定义。
TYPE_PARAMETER:表示该注解能写在类型参数的声明语句中。类型参数声明如:、
TYPE_USE:表示注解可以在任何用到类型的地方使用。