【Java进阶】众所周知的 Java 8 新特性(二)

145 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

函数式接口

定义:接口中有且只有一个抽象方法,便称为函数式接口

@FunctionalInterface 
public interface MyFunctionalInterface { 
    void myMethod(); 
}

@FunctionalInterface:用于一个接口的定义上,一旦使用该注解定义接口,则编译器将会强制检查该接口是否确实有且只有一个抽象方法,否则报错。

特征

  • 可选类型声明:可以不声明参数类型,编译器将统一识别参数值

  • 可选参数圆括号():一个参数可以不定义圆括号,但没有参数或多个参数需要定义圆括号

  • 可选大括号{}:若 Lambda 体只有一个语句,可以不写 {}

  • 可选返回关键字 return:若 Lambda 体只有一个表达式返回值,则可以省略 return 和 {}

常见函数式接口

位于java.util.function包下

image.png

方法引用

定义:"::"引用运算符,包含引用运算符的表达式称为方法引用

语法

  • 对象引用::实例方法名 System.out::println
  • 类名::静态方法名 Math::random
  • 类名::实例方法名 Product::getName
  • 类名::new Product::new

接口进化

JDK 1.8 及之后版本,接口中允许包含 default 方法和 static 方法并指定方法体的具体实现

image.png

默认方法

  • 能够在接口名称不变和对已有的若干实现类不产生任何影响的情况下,追加新的方法定义,这种方法称为默认方法
  • 接口冲突
    • 原因:同时实现的多个接口中具有方法签名相同的 default 方法
    • 解决:实现类重写该方法 image.png

静态方法

  • 可用于设计工具类

Optional<T>

Optional<T>是 Java 8 新加的容器,只存放0个或1个元素,用于防止出现 NullpointException

boolean isPresent():判断容器是否有值

T get():获取容器中的元素,若容器为空则抛出 NoSuchElement 异常。

List<Integer> list = Arrays.asList(1, 2, 1, 3, -1, 2, 4);
Optional<Integer> first = list.stream().findFirst();
if (first.isPresent()) {
    System.out.println("返回第一个元素:" + first.get());
}
// 更优雅的方式
first.ifPresent(integer -> System.out.println("返回第一个元素:" + integer));

Optional<Integer> anyEle = list.stream().findAny();
System.out.println(anyEle.get());
拓展知识点:并行和并发

并行是指多个任务发生在同一时刻,必须在多核 CPU 下
并发是指多个任务发生在同一时间段,由 CPU 切换执行

数据并行化/并行流

  • 将数据分成块,为每块数据分配单独的处理单元
  • 普通流转为并行流 parallel()
  • 直接获取并行流 parallelStream()
  • 影响并行流性能的主要因素
    • 数据大小:数据分解与合并都会带来开销,只有数据足够大,并行处理才有意义
    • 源数据结构:一般采用集合进行并行处理
    • 装箱:即包装类比基本数据类型处理要快
    • 核的数量:在多核情况下,才有必要进行并行化处理
    • 单元处理开销:每个元素处理的时间越长,并行的效果将更明显