本文是对Java语言新特性的介绍,对Java发展历史或当下生产环境中主要使用到的特性进行简单描述,
第 1 章 Java8 新特性
1.1 Lambda 表达式
- Lambda 是一个匿名函数,可以理解为可以传递的代码。
- 语法:
->
Lambda 操作符、箭头操作符,符号左侧为参数列表,右侧为 Lambda 体(方法体)- 格式一:无参、无返回值:
Runnable r1 = () -> {System._out_.println("hello");};
- 如果 Lambda 体只有一条语句,则
{}
可以省略:Runnable r1 = () -> System._out_.println(str);
- 如果 Lambda 体只有一条语句,则
- 格式二:一个参数、无返回值:
Consumer<String> con = (String str) -> {System._out_.println(str);};
- 一句 Lambda 体可省略
{}
:Consumer<String> con = (String str) -> System._out_.println(str);
- 省略参数类型(根据上下文环境自动类型推断):
Consumer<String> con = (str) -> System._out_.println(str);
- 省略形参
()
:Consumer<String> con = str -> System._out_.println(str);
- 一句 Lambda 体可省略
- 格式三:一个参数,有返回值
- return 可以省略,同时必须省略
{}
?
- return 可以省略,同时必须省略
- 格式四:两个及以上参数,无返回值?
- 格式五:两个及以上参数,有返回值:
- 多个 Lambda 体:
Compartor<Integer> com = (Integer x, Integer y) -> {System._out_.println("hello");return Integer.compare(x,y};
- 省略参数类型(根据上下文环境自动类型推断):
Compartor<Integer> com = (x, y) -> {System._out_.println("hello");return Integer.compare(x,y};
- 一个 Lambda 体:
Compartor<Integer> com = (Integer x, Integer y) -> {return Integer.compare(x,y};
- 省略参数类型(根据上下文环境自动类型推断):Compartor<Integer> com = (x, y) -> {return Integer.compare(x,y};
- 一句 Lambda 体可省略
{}
及return
:Compartor<Integer> com = (x, y) -> Integer.compare(x,y);
- 注意:省略
{}
必须省略return
,即Compartor<Integer> com = (x, y) -> return Integer.compare(x,y);
为错误形式
总结:
- 左边:
- 形参列表的类型可以省略
- 只有一个参数
()
可以省略
- 右边:
- Lambda 一般使用
{}
包裹 - 一条 Lambda 可以省略
{}
- 一条 return 省略语句,省略
{}
必须省略return
- Lambda 一般使用
- 多个 Lambda 体:
- 格式一:无参、无返回值:
- 本质:作为接口的实例(且是该接口只有一个方法,这是唯一的实例)
- 注意点:
- Lambda 只是代替了声明部分,要想执行还得调用其方法。
- Lambda 之所以能这样写,是因为这些接口内部定义的方法只有这一个。
- 使用场景:
- 函数式接口
- 函数式接口需要匿名实现类
- Lambda 表达式作为参数传递(调用时)
1.2 Stream API
1.2.1 概述
- Stream API 是设计用于处理 MongDB、Radis 等 NoSQL 数据库,因为这类数据库需要 Java 层面去处理数据
- Stream API 位于
java.util.stream
包下。使用了函数式编程风格。 - Stream API 是设计用于处理 MongDB、Radis 等 NoSQL 数据库的,而这类数据库是 key-val 类型的,即 Java 中集合类型。所以 Stream API 是处理集合的。
- Stream API 特点:
- Stream 不会存储元素,而是处理元素
- Stream 处理元素不会改变原数据,而会返回一个 Stream
- Stream 是面向 CPU 的,是完成计算的
- Stream 的操作是延迟执行的,即需要得到结果时才执行
- Stream 操作步骤:
- 创建 Stream,得到 Stream 的实例
- 中间操作(中间操作链),对数据原进行数据处理
- 终止操作,执行终止操作后,就开始执行中间操作链,并得到结果。执行完毕进行废弃。
1.2.2 创建 Stream
- 通过 Collection 集合创建:集合的接口中定义了两个获取 Stream 流的默认方法,通过该接口的实例化对象,可以创建 Stream。
- 顺序流:
default Stream<E> stream()
- 并行流:
default Stream<E> parallelStream()
- 顺序流:
- 通过 Arrays 的静态方法:
static <T> Stream<T> stream(T[] array)
- 重载类型:
public static IntStream stream(int[] array)
public static LongStream stream(long[] array)
public static DoubleStream stream(double[] array)
- 通过 Stream 类的静态方法
of()
方法:public static<T> Stream<T> of(T... values)
,有限流。iterate()
方法——迭代:public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
,无限流generate()
方法——生成:public static<T> Stream<T> generate(Supplier<T> s)
,无限流
1.2.3 中间操作
- 筛选与切片:
filter(Predicate p)
:获取满足该 p 条件的元素,接收 Lambda 表达式参数distinct()
:去重,通过元素的 hasCode()和 equals()判断limit(Long maxSize)
:截断,获取指定个数的元素skip(Long n)
:跳过,跳过指定个数的元素
- 映射:
map(Function f)
:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。mapToDouble(ToDoubleFunction f)
mapToInt(ToIntFunction f)
mapToLong(ToLongFunction f)
flatMap(Function f)
:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
- 排序:
sorted()
:产生一个新流,其中按自然顺序排序sorted(Comparator com)
:产生一个新流,其中按比较器顺序排序
1.2.4 终止操作
- 匹配:返回 Boolean
allMatch(Predicate p)
:是否匹配所有元素anyMath(Predicate p)
:是否存在匹配的元素noneMatch(Predicate p)
:是否没有匹配所有元素
- 查找:
findFirst()
:返回第一个元素findAny()
:返回当前流中的任意元素count()
:返回流中元素总数max(Comparator c)
:返回流中最大值min(Comparator c)
:返回流中最小值forEach(Consumer c)
:内部迭代,遍历元素
- 归约:
reduce(T iden, BinaryOperator b)
:可以将流中元素反复结合起来,得到一个值。返回 Treduce(BinaryOperator b)
:可以将流中元素反复结合起来,得到一个值。返回 Optional备注:map 和 reduce 的连接通常称为 map reduce 模式,因 Google 用它来进行网络搜索而出名。
- 收集:
collect(Collector c)
:将流转换为其他形式。接收一个 Collector 接口的实现,用于给 Stream 中元素做汇总的方法
1.3 Optional 类
1.3.1 概述
- Optional
类(java.util.Optional) 是一个容器类, 是一个可以为 null 的容器对象。如果值存在则 isPresent()方法会返回 true,调用 get()方法会返回该对象。 - 好处:原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念。并且可以避免空指针异常。
1.3.2 创建 Optional 类对象
Optional.of(T t)
: 创建一个 Optional 实例, t 必须非空Optional.empty()
: 创建一个空的 Optional 实例Optional.ofNullable(T t)
: t 可以为 null
1.3.3 判断 Optional 是否包含对象
boolean isPresent()
: 判断是否包含对象void ifPresent(Consumer<? super T> consumer)
:如果有值,就执行 Consumer 接口的实现代码,并且该值会作为参数传给它。
1.3.4 获取 Optional 容器的对象
T get()
: 如果调用对象包含值,返回该值,否则抛异常T orElse(T other)
:如果有值则将其返回,否则返回指定的 other 对象。T orElseGet(Supplier<? extends T> other)
:如果有值则将其返回,否则返回由 Supplier 接口实现提供的对象。T orElseThrow(Supplier<? extends X> exceptionSupplier)
:如果有值则将其返回,否则抛出由 Supplier 接口实现提供的异常。
1.4 函数式(Functional)接口
- 只能创建一个抽象方法的接口。
- 定义接口时使用
@FunctionalInterface
注解,用于编译时检查。同时 javadoc 会包含该声明@FunctionalInterface
注解声明的接口,只能包含一个抽象方法,可以包含多个默认方法,也可以包含多个静态方法。
- Java8 的函数式接口定义在
java.util.function
中 - 函数式接口的理解:
- 函数式接口的出现,使 Java 既可以支持 OOP,还可以支持 OOF(面向函数编程)
- 但在 Java 语言中,Lambda 表达式是对象,而不是函数,恰恰是因为函数式接口——特别的对象类型
- Lambda 表达式就是一个函数式接口的实例。
- 即,只要一个对象是函数式接口的实例,那么该对象就可以用 Lambda 表达式表示。
- Java 内置四大核心函数式接口:
- 其他内置接口:
1.5 方法引用及构造器引用
1.5.1 方法引用
- 对 Lambda 表达式的优化简写,通过方法的名字指向一个方法。
- 语法:
::
将类(或对象)与方法名分隔开 - 格式:
对象::实例方法名
- 没有
对象::静态方法名
,因为没必要
- 没有
类::静态方法名
类::实例方法名
- 使用要求:接口中的抽象方法的参数列表、返回值类型,与方法引用的方法的参数列表和返回值类型一致。
类::实例方法名
会出现抽象方法与方法引用方法参数列表匹配的情况,但还是可以使用,原因是,参数列表中第一个参数是作为方法的调用者出现的。
1.5.2 构造器引用
- 使用要求:接口中的抽象方法的参数列表,与构造器的参数列表和一致,且抽象方法的返回值为构造器对应类的对象.
- 格式:
ClassName::new
1.5.3 数组引用
- 格式:
type[]::new
原文链接: https://sk370.github.io/2022/05/28/javase/Java新特性/
版权声明: 转载请注明出处。