Java8 新特性
一、接口的默认方法
1.1 为什么引入此方法
接口功能扩展
接口可以有实现方法,且无需实现类实现其方法。
- 解决接口的修改与现有的实现不兼容的问题;
- 接口支持申明带实现的方法;
1.2 什么是默认方法
- 接口中使用default关键字修饰的方法:一个接口中可以存在多个默认方法
- 静态默认方法:接口中可以申明静态方法
1.3 和抽象类的区别
- 继承关系:一个类只能继承一个抽象类,但可以实现多个接口
- 变量:抽象类有实例变量,接口只能有类变量
1.4 多个默认方法解决方案
- 创建自己的默认方法,来覆盖重写接口的默认方法
- 使用super来现实调用指定的默认方法
二、lambda表达式
2.1 什么是lambda表达式
lambda表达式通常是一个函数,Java中的lambda表达式将函数的概念引入到语言中。
lambda理解为一种具有更紧凑语法的匿名方法,允许省略修饰符、返回类型、特种情况允许省略参数类型。
2.2 为什么使用lambda表达式
- 代码简洁、使用灵活、更具阅读性
- lambda表达式是一种紧凑的、传递行为的方式
2.3 语法与使用
- 语法
- (parameters)->expression
- (parameters)->{statements;}
- 使用
- 使用lambda表达式排序集合
Collections.sort(list,(String a,String b)->b.compareTo(a));
list.sort((a,b)->b.compareTo(a)); - 与stream结合使用
list.stream().filter(§->(p.getSalary()>1400)).collect(Collectors.toList());
- 使用lambda表达式排序集合
2.4 lambda表达式作用域
- 访问局部变量
- 使用final修饰的局部变量
- 隐性的final语法,即在lambda表达式之后不被修改的局部变量
- 访问对象字段与静态变量
- 可读可写
- 不可访问接口的默认方法
- 使用this会引用创建该lambda表达式的方法的this参数
三、函数式接口
3.1 什么是函数式接口
- 定义:有且仅有一个抽象方法的接口
3.2 为什么有函数式接口
- lambda表达式是对象,必须依附于一类特别的对象类型,即函数式接口。
- 函数式接口用于表示lambda表达式的类型。
3.3 内置四大核心函数式接口
函数式接口 | 参数类型 | 返回类型 | 用途 |
---|---|---|---|
Consumer消费型接口 | T | void | 对类型为T的对象应用操作,包含方法void accept(T t) |
Predicate断定型接口 | T | boolean | 确定类型为T的对象是否满足某约束,并返回boolean值。包含方法boolean test(T t) |
Supplier供给型接口 | 无 | T | 返回类型为T的对象,包含方法T get() |
Function<T,R>函数型接口 | T | R | 对类型为T的对象应用操作,并返回R类型的对象结果。包含方法R apply(T t) |
四、方法的引用
4.1 为什么有方法引用
就是一个另类的lambda表达式,仅调用一个已存在的方法,不做其他处理。操作符是“::”。
4.2 方法引用的四种形式
类型 | 语法 |
---|---|
静态方法引用 | 类名::静态方法 |
非静态方法引用 | 对象::非静态方法 |
构造方法引用 | 类名::new |
本类非静态方法引用 | this::非静态方法 |
//静态方法引用(类名::方法名)
Function<String,Integer> fun1=s->Integer.parseInt(s);
Function<String,Integer> fun2=Integer::parseInt;
//非静态方法引用
Function<String,Boolean> fun1=s->list.add(s);
Function<String,Boolean> fun2=s->list::add;
//构造方法引用(类名::new)
Function<String,Method> fun1=s->new Method(s);
Function<String,Method> fun1=Method::new;//类引用单参构造方法
Function<String,Integer,Method> fun2=(s,i)->new Method(s,i);
Function<String,Integer,Method> fun2=Method::new;//类引用双参构造方法
//本类非静态方法引用(this::方法名)
Function<String,Integer> fun1=s->love(s);
Function<String,Integer> fun1=this::love;
Function<String,Integer> fun2=s->super.love(s);
Function<String,Integer> fun2=super::love;//扩展:子类可以使用suoer调用父类方法
五、Optional类
5.1 为什么有Optional类
- 避免出现空指针异常,使代码更具有可读性.
5.2 Optional类的描述
- 这是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
5.3 Optuonal类使用总结
方法 | 方法描述 |
---|---|
of(T t) | t为null时报空指针异常,否则创建一个Op实例 |
empty() | 创建一个空的Op实例 |
ofNullable(T t) | t不为null时创建Op实例,否则创建空的Op实例 |
get() | 如果Op有值将其返回,否则抛出NoSuchElementException |
isPresent() | 判断是否包涵值,返回boolean值 |
orElse(T t) | 如果调用对象包涵值,返回该值,否则返回t |
orElseGet(Supplier s) | 如果调用对象包涵值,返回该值,否则返回s获取的值 |
map(Function f) | 如果有值对其处理,并返回处理后的Op,否则返回Op.empty() |
flatMap(Function mapper) | 与map类似,要求返回值必须是Optional |
filter(Predicate p) | 如果有值且满足断言条件返回该值得Op对象,否则返回空的Op对象 |
of(T t)
//工厂方法创建Optional实例
Optional<String> name = Optional.of("optional");
//传入参数为null,抛出NullPointerException.
Optional<String> someNull = Optional.of(null);
empty()
//Optional.empty() : 创建一个空的 Optional 实例
Optional<Object> empty = Optional.empty();
ofNullable(T t)
//创建一个值为'null'的Optional
Optional empty = Optional.ofNullable(null);
get()
//执行下面的代码会输出:No value present
try {
//在空的Optional实例上调用get(),抛出NoSuchElementException
System.out.println(empty.get());
} catch (NoSuchElementException ex) {
System.out.println(ex.getMessage());}
isPresent()
//isPresent() : 判断是否包含值
Optional<Employee> employees = Optional.ofNullable(null);
if(employees.isPresent()){ System.out.println("不为空");
}else{ System.out.println("为空");
}
ofElse(T t)
//如果值不为null,orElse方法返回Optional实例的值。
//如果为null,返回传入的消息。
//输出:There is no value!
System.out.println(empty.orElse("There is no value !"));
//输出:optional
System.out.println(name.orElse("There is some value!"));
orElseGet(Supplier s)
//orElseGet与orElse方法类似,区别在于orElse传入的是默认值
//orElseGet可以接受一个lambda表达式生成默认值。
//输出:Default Value
System.out.println(empty.orElseGet(() -> "Default Value"));
//输出:optional
System.out.println(name.orElseGet(() -> "Default Value"));
orElseThrow(Supplier s)
try {
//orElseThrow与orElse方法类似。与返回默认值不同
//orElseThrow会抛出lambda表达式或方法生成的异常
empty.orElseThrow(ValueAbsentException::new);
} catch (Throwable e) {
//输出: No value present in the Optional instance
System.out.println(e.getMessage());
}
//ValueAbsentException定义class
ValueAbsentException extends Throwable {
public ValueAbsentException() {
super();
}
public ValueAbsentException(String msg) {
super(msg);
}
@Override
public String getMessage() { return "No value present in the Optional instance"; }}
map(Function f)
//map方法执行传入的lambda表达式参数对Optional实例的值进行修改。
//为lambda表达式的返回值创建新的Optional实例作为map方法的返回值。
Optional<String> upperName = name.map((value) -> value.toUpperCase());
System.out.println(upperName.orElse("No value found"));
flatMap(Function mapper)
//flatMap与map(Function)非常类似,区别在于传入方法的lambda表达式的返回类型。
//map方法中的lambda表达式返回值可以是任意类型,在map函数返回之前会包装为Optional。
//但flatMap方法中的lambda表达式返回值必须是Optionl实例。
upperName = name.flatMap((value) -> Optional.of(value.toUpperCase()));
System.out.println(upperName.orElse("No value found"));
//输出OPTIONAL
filter(Predicate p)
//filter方法检查给定的Option值是否满足某些条件。
//如果满足则返回同一个Option实例,否则返回空Optional。
Optional<String> longName = name.filter((value) -> value.length() > 6);
System.out.println(longName.orElse("The name is less than 6 characters"));
//输出optional
六、Stream
6.1 为什么java8加入Stream
- Stream是对集合对象功能的增强,专注于对集合对象进行各种非常便利、高效的聚合操作或者大批数据操作。
- 使代码更加简洁、易读。
6.2 什么是Stream
- 数据渠道,用于操作数据源所生成的元素序列。
- 像高级版本的迭代器,可以并行化操作。并行操作依赖于Fork/Join框架
6.3 Stream的使用
- 创建stream
- 中间操作:通过对个中间操作将stream转为另外一个stream
- 终止操作:获取结果,触发之前的懒操作的执行。
6.3.1 创建流
- 集合、数组、文件等都可以转成stream来处理。
- Collection接口提供Stream()方法。
- Map集合调用entrySet()方法转为Set 集合再转为Stream流。
6.3.2 中间操作
- 筛选与切片
方法 | 描述 |
---|---|
filter(Predicate) | 接收一个lambda,从流中排除某些元素 |
distinct() | 去重 |
limit(long maxSize) | 截断流,使其元素不超过给定数量 |
skip(long n) | 跳过元素,返回一个扔掉前n个元素的流,于limit互补 |
- 映射
方法 | 描述 |
---|---|
map(Function f) | 接收一个函数作为参数,该函数会被应用到每一个元素上,并将其映射成一个新的元素 |
mapToDouble(ToDoubleFunction f) |
- 排序
方法 | 描述 |
---|---|
sorted() | 产生一个限流,按自然顺序排序 |
sorted(Comparator comp) |
6.3.3 终止操作
- 查找于匹配
方法 | 描述 |
---|---|
boolean | |
allMatch(Predicate p) | 检查是否匹配所有元素 |
findFist() | |
count() | |
max(Comparator c) | |
forEach(Consumer c) |
- 规约
方法 | 描述 |
---|---|
reduce(T iden,BinaryOperator b) | 可以将流中元素反复结合起来,得到一个值,返回T |
reduce(BinaryOpertor b) | 返回Optional |
- 收集
方法 | 描述 |
---|---|
collect(Collector c) | 将流转为其他形式,接收一个Collector实现,用于给stream中的元素做汇总的方法 |
- Collector静态方法
方法 | 返回类型 | 作用 |
---|---|---|
toList | List | 把流中元素收集到List |
toSet | Set | |
counting | Long | 计算流中元素个数 |
joining | String | 链接流中的每个字符串 |
groupingBy | Map<K,List> | 根据某属性对流分组,属性为K,结果为V |
partitioningBy | Map<Boolean,List> | 根据true或false进行分区 |