1. Lambda表达式
Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
使用 Lambda 表达式可以使代码变的更加简洁紧凑。
Lambda语法
// 类型声明
MathOperation addition = (int a, int b) -> a + b;
// 不用类型声明
MathOperation subtraction = (a, b) -> a - b;
// 大括号中的返回语句
MathOperation multiplication = (int a, int b) -> { return a * b; };
// 没有大括号及返回语句
MathOperation division = (int a, int b) -> a / b;
// 不用括号
GreetingService greetService1 = message ->
System.out.println("Hello " + message);
// 用括号
GreetingService greetService2 = (message) ->
System.out.println("Hello " + message);
2.方法引用
方法引用通过方法的名字来指向一个方法。
方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
方法引用使用一对冒号::
。
-
构造器引用:它的语法是Class::new,或者更一般的Class< T >::new实例如下:
final Car car = Car.create( Car::new ); final List< Car > cars = Arrays.asList( car );
-
静态方法引用:它的语法是Class::static_method,实例如下:
cars.forEach( Car::collide );
-
特定类的任意对象的方法引用:它的语法是Class::method实例如下:
cars.forEach( Car::repair );
-
特定对象的方法引用:它的语法是instance::method实例如下:
final Car police = Car.create( Car::new ); cars.forEach( police::follow );
3.函数式接口
函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
函数式接口可以被隐式转换为 lambda 表达式。
Lambda 表达式和方法引用(实际上也可认为是Lambda表达式)上。
序号 | 接口 & 描述 |
---|---|
1 | BiConsumer代表了一个接受两个输入参数的操作,并且不返回任何结果 |
2 | BiFunction代表了一个接受两个输入参数的方法,并且返回一个结果 |
3 | BinaryOperator代表了一个作用于于两个同类型操作符的操作,并且返回了操作符同类型的结果 |
4 | BiPredicate代表了一个两个参数的boolean值方法 |
5 | BooleanSupplier代表了boolean值结果的提供方 |
6 | Consumer代表了接受一个输入参数并且无返回的操作 |
7 | DoubleBinaryOperator代表了作用于两个double值操作符的操作,并且返回了一个double值的结果。 |
8 | DoubleConsumer代表一个接受double值参数的操作,并且不返回结果。 |
9 | DoubleFunction代表接受一个double值参数的方法,并且返回结果 |
10 | DoublePredicate代表一个拥有double值参数的boolean值方法 |
11 | DoubleSupplier代表一个double值结构的提供方 |
12 | DoubleToIntFunction接受一个double类型输入,返回一个int类型结果。 |
13 | DoubleToLongFunction接受一个double类型输入,返回一个long类型结果 |
14 | DoubleUnaryOperator接受一个参数同为类型double,返回值类型也为double 。 |
15 | Function接受一个输入参数,返回一个结果。 |
16 | IntBinaryOperator接受两个参数同为类型int,返回值类型也为int 。 |
17 | IntConsumer接受一个int类型的输入参数,无返回值 。 |
18 | IntFunction接受一个int类型输入参数,返回一个结果 。 |
19 | IntPredicate:接受一个int输入参数,返回一个布尔值的结果。 |
20 | IntSupplier无参数,返回一个int类型结果。 |
21 | IntToDoubleFunction接受一个int类型输入,返回一个double类型结果 。 |
22 | IntToLongFunction接受一个int类型输入,返回一个long类型结果。 |
23 | IntUnaryOperator接受一个参数同为类型int,返回值类型也为int 。 |
24 | LongBinaryOperator接受两个参数同为类型long,返回值类型也为long。 |
25 | LongConsumer接受一个long类型的输入参数,无返回值。 |
26 | LongFunction接受一个long类型输入参数,返回一个结果。 |
27 | LongPredicateR接受一个long输入参数,返回一个布尔值类型结果。 |
28 | LongSupplier无参数,返回一个结果long类型的值。 |
29 | LongToDoubleFunction接受一个long类型输入,返回一个double类型结果。 |
30 | LongToIntFunction接受一个long类型输入,返回一个int类型结果。 |
31 | LongUnaryOperator接受一个参数同为类型long,返回值类型也为long。 |
32 | ObjDoubleConsumer接受一个object类型和一个double类型的输入参数,无返回值。 |
33 | ObjIntConsumer接受一个object类型和一个int类型的输入参数,无返回值。 |
34 | ObjLongConsumer接受一个object类型和一个long类型的输入参数,无返回值。 |
35 | Predicate接受一个输入参数,返回一个布尔值结果。 |
36 | Supplier无参数,返回一个结果。 |
37 | ToDoubleBiFunction接受两个输入参数,返回一个double类型结果 |
38 | ToDoubleFunction接受一个输入参数,返回一个double类型结果 |
39 | ToIntBiFunction接受两个输入参数,返回一个int类型结果。 |
40 | ToIntFunction接受一个输入参数,返回一个int类型结果。 |
41 | ToLongBiFunction接受两个输入参数,返回一个long类型结果。 |
42 | ToLongFunction接受一个输入参数,返回一个long类型结果。 |
43 | UnaryOperator接受一个参数为类型T,返回值类型也为T。 |
4.Stream
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
什么是 Stream?
Stream(流)是一个来自数据源的元素队列并支持聚合操作
- 元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
- 数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
- 聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。
和以前的Collection操作不同, Stream操作还有两个基础的特征:
- Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
- 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。
生成流
Stream无限流:通过函数式接口生成
数组的stream()
集合接口:
- stream()——串行流
- parallelstream()——并行流
中间操作
- filter()
- map()
- flatMap()
- sorted()
- parallel()
终端操作
- forEach()
- toArray()
- collect()
- limit()
- reduce()
- 查找与匹配
- allMatch
- anyMatch
- noneMatch
- findFirst
- findAny
- count
- max
- min
5.Optional 类
Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
Optional 类的引入很好的解决空指针异常。
类声明
public final class Optional<T> extends Object
类方法
序号 | 方法 & 描述 |
---|---|
1 | static Optional empty()返回空的 Optional 实例。 |
2 | boolean equals(Object obj)判断其他对象是否等于 Optional。 |
3 | Optional filter(Predicate predicate)如果值存在,并且这个值匹配给定的 predicate,返回一个Optional用以描述这个值,否则返回一个空的Optional。 |
4 | Optional flatMap(Function> mapper)如果值存在,返回基于Optional包含的映射方法的值,否则返回一个空的Optional |
5 | T get()如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException |
6 | int hashCode()返回存在值的哈希码,如果值不存在 返回 0。 |
7 | void ifPresent(Consumer consumer)如果值存在则使用该值调用 consumer , 否则不做任何事情。 |
8 | boolean isPresent()如果值存在则方法会返回true,否则返回 false。 |
9 | Optional map(Function mapper)如果有值,则对其执行调用映射函数得到返回值。如果返回值不为 null,则创建包含映射返回值的Optional作为map方法返回值,否则返回空Optional。 |
10 | static Optional of(T value)返回一个指定非null值的Optional。 |
11 | static Optional ofNullable(T value)如果为非空,返回 Optional 描述的指定值,否则返回空的 Optional。 |
12 | T orElse(T other)如果存在该值,返回值, 否则返回 other。 |
13 | T orElseGet(Supplier other)*如果存在该值,返回值, 否则触发 other,并返回 other 调用的结果。 |
14 | T orElseThrow(Supplier exceptionSupplier)如果存在该值,返回包含的值,否则抛出由 Supplier 继承的异常 |
15 | String toString()返回一个Optional的非空字符串,用来调试 |
6.日期时间 API
旧版的java中,日期时间API存在诸多问题:
- 非线程安全 − java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一。
- 设计很差 − Java的日期/时间类的定义并不一致,在java.util和java.sql的包中都有日期类,此外用于格式化和解析的类在java.text包中定义。java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql包并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计。
- 时区处理麻烦 − 日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Calendar和java.util.TimeZone类,但他们同样存在上述所有的问题。
在 java.time 包下提供了很多新的 API。以下为两个比较重要的 API:
- Local(本地) − 简化了日期时间的处理,没有时区的问题。
- Zoned(时区) − 通过制定的时区处理日期时间。
具体的方法:
- LocalDateTime、 LocalDate、 LocalTime()
- Instant 时间戳
- Duration 计算时间间隔
- Period 计算日期间隔
- TemporalAdjust 时间校正器
- DateTimeFormatter格式化时间/日期
- ZonedDate、ZonedTime、ZonedDateTime