1.Java8新特性-Lambda表达式
2.1关于Java8新特性简介
Java 8是Java编程语言的一个重大版本更新,于2014年3月发布。它引入了许多新特性和改进,使得Java编程更加方便和高效。
下面是Java 8的主要新特性:
Lambda表达式:Lambda表达式是Java 8中最引人注目的特性之一。它允许开发人员使用更简洁的语法来定义匿名函数,从而使代码更简洁、可读性更强。
函数式接口:Java 8引入了函数式接口的概念,它是只包含一个抽象方法的接口。这使得开发人员可以使用Lambda表达式来实现接口的抽象方法,从而更方便地实现函数式编程。
Stream API:Stream API是Java 8中一个新增的用于处理集合数据的API。它提供了一种新的编程模型,可以通过简洁的语法和方法链来操作集合数据,例如过滤、映射、排序等。
默认方法:Java 8允许在接口中定义默认方法,这是一种具有默认实现的接口方法。这使得开发人员可以在接口中添加新的方法,而不会破坏已有的实现类。
方法引用:方法引用是一种更简洁的Lambda表达式语法,它允许开发人员直接引用已有的方法,而不需要重新编写Lambda表达式。
Optional类:Optional类是一个用于处理可能为空的值的容器类。它提供了一些方法来避免空指针异常,例如orElse()、isPresent()等。
新的日期和时间API:Java 8引入了全新的日期和时间API,提供了更好的日期和时间处理方式,解决了以前日期和时间处理方面的一些问题。
2.2Lambda及其使用举例
1.Lambda表达式的使用举例:
(o1,o2) - > Integer.compare(o1,o2);
2.Lambda表达式的格式举例:
lambda形参列表 - > lambda体
3.Lambda表达式的格式
- > :lambda操作符或箭头操作符。
- >的左边:lambda形参列表,对应着要重写的接口中的抽象方法的形参列表。
- >的右边:lambda体,对应着接口的实现类要重写的方法的方法体。
4.Lambda表达式的本质:
> 一方面,lambda表达式作为接口的实现类的对象。 --->"万事万物皆对象"> 另一方面,lambda表达式是一个匿名函数。
5.函数式接口:
5.1 什么是函数式接口?为什么需要函数式接口?> 如果接口中只声明有一个抽象方法,则此接口就称为函数式接口。
> 因为只有给函数式接口提供实现类的对象时,我们才可以使用lambda表达式。
5.2 api中函数式接口所在的包jdk8中声明的函数式接口都在java.util.function包下。
5.3 4个基本的函数式接口
函数式接口 称谓 参数类型 用途 Consumer<T> 消费型接口 T 对类型为T的对象应用操作,包含方法:void accept(T t) Supplier<T> 供给型接口 无 返回类型为T的对象,包含方法:T get() Function<T,R> 函数型接口 T 对类型为T的对象应用操作,并返回结果,结果是R类型的对象,包含方法:R apply(T t) Predicate<T> 判断型接口 T 确定类型为T的对象是否满足某约束条件,并返回Boolean值,包含方法:
boolean test(T t)
2.方法引用和构造器引用
2.1方法引用
1.举例:
Integer :: compare
2.方法引用的理解
> 方法引用可以看作是基于lambda表达式的进一步刻画。
> 当需要提供一个函数式接口的实例时,我们可以使用lambda表达式提供实例。
> 当满足一定的条件的情况下,还可以使用方法引用或构造器引用替换lambda表达式。
3.方法引用的本质
方法引用作为了函数接口的实例。
4.格式
类(或对象) :: 方法名
5.具体使用情况说明
情况一:对象 :: 实例方法
要求:函数式接口中的抽象方法a与其内部实现时调用的对象的某个方法b的形参列表和返回值类型都相同。
此时,可以考虑使用方法b实现对方法a的替换、覆盖。此替换或覆盖即为方法引用。
注意:此方法b是非静态的方法,需要对象调用。情况二:类 :: 静态方法
要求:函数式接口中的抽象方法a与其内部实现时调用的对象的某个静态方法b的形参列表和返回值类型都相同。
此时,可以考虑使用方法b实现对方法a的替换、覆盖。此替换或覆盖即为方法引用。
注意:此方法b是静态的方法,需要对象调用。情况三:类 :: 实例方法
要求:函数式接口中的抽象方法a与其内部实现时调用的对象的某个方法b的形参列表和返回值类型都相同。
同时,抽象方法a中有n个参数,方法b中有n-1个参数,且抽象方法a的第一个参数作为b的调用者,且方法a中的后n-1个参数与方法b的n-1个参数的类型相同。此时,可以考虑使用方法b实现对方法a的替换、覆盖。此替换或覆盖即为方法引用。
2.2构造器引用
1.格式
类名 :: new
2.说明
> 调用了类名对应的类中的某一个确定的构造器。
> 具体调用的是类中的哪一个构造器呢?取决于函数式接口的抽象方法的形参列表!
3.Java8新特性:StreamAPI
3.1Stream API vs 集合框架
Stream API 关注的是多个数据的计算(排序、查找、过滤、映射、遍历等),面向CPU的。
集合关注的数据的存储,向下内存的。
Stream API 之于集合,类似于S0L之于数据表的查询。
3.2使用说明
①Stream 自己不会存储元素,
②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
③stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。即一旦执行终止操作,就执行中间操作链,并产生结果。
④ stream一旦执行了终止操作,就不能再调用其它中间操作或终止操作了。3.3Stream 执行流程
步骤一:Stream实例化
实例化Stream有三种方法:
通过集合创建Stream:可以通过集合类的stream()方法获取一个Stream对象。例如:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); Stream<Integer> stream = list.stream();
通过数组创建Stream:可以通过Arrays类的stream()方法获取一个Stream对象。例如:
int[] array = {1, 2, 3, 4, 5}; IntStream stream = Arrays.stream(array);
通过Stream的静态方法创建Stream:Stream类提供了一些静态方法用于创建Stream对象。例如:
- Stream.of():可以接收任意数量的参数,并将其作为Stream的元素。
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
- Stream.empty():创建一个空的Stream对象。
Stream<Object> stream = Stream.empty();
- Stream.generate():可以通过提供的Supplier函数无限生成Stream元素。
Stream<Integer> stream = Stream.generate(() -> 1);
- Stream.iterate():可以通过提供的初始值和UnaryOperator函数生成Stream。其中,初始值作为第一个元素,然后通过应用UnaryOperator函数来生成后续元素。
Stream<Integer> stream = Stream.iterate(0, n -> n + 1);
步骤二:一系列的中间操作
1.筛选与切片
2.映射
3.排序
步骤三:执行终止操作
4.JDK8-17新特性
模块化系统:JDK 9引入了模块化系统,使用Java Platform Module System(JPMS)可以将代码划分为模块,控制模块之间的依赖关系,提高了代码的可维护性和安全性。
JShell:JDK 9引入了JShell,这是一个交互式的Java编程工具,可以即时执行Java代码片段进行测试和调试。
私有接口方法:JDK 9允许在接口中定义私有方法,这些方法只能在接口内部使用,方便了接口的实现和维护。
Reactive Streams API:JDK 9引入了Reactive Streams API,提供了一种处理流和异步数据流的标准化方式,使得开发响应式应用程序更加容易。
集合工厂方法:JDK 9引入了一系列集合工厂方法,例如List.of()、Set.of()和Map.of(),方便创建和初始化不可变集合。
接口的私有方法和私有静态方法:JDK 9允许在接口中定义私有方法和私有静态方法,这些方法只能在接口内部使用,方便了接口的实现和扩展。
钻石操作符的支持:JDK 10引入了钻石操作符的支持,可以使用var关键字来自动推断泛型类型。
局部变量类型推断:JDK 10引入了局部变量类型推断,可以使用var关键字来自动推断局部变量的类型。
Epsilon垃圾收集器:JDK 11引入了Epsilon垃圾收集器,这是一种无操作的垃圾收集器,适用于性能测试和短暂的内存压力测试。
HTTP/2 客户端:JDK 11引入了原生的HTTP/2客户端支持,可以更高效地进行网络通信。
嵌套访问控制:JDK 11引入了嵌套访问控制(Nest-based Access Control),提供了更加细粒度的类访问控制机制。
ZGC:JDK 11引入了Z Garbage Collector(ZGC),这是一种低延迟的垃圾回收器,适用于大内存环境下的高吞吐量应用程序。
应用程序类数据共享(Application Class-Data Sharing):JDK 14引入了应用程序类数据共享(AppCDS),可以在应用程序启动时将常用类的数据结构缓存在共享内存中,提高了应用程序的启动性能。
Records:JDK 14引入了Records,这是一种简化POJO类的语法,可以自动生成常见的方法(如equals()和hashCode()),减少了代码的冗余。
并发数据结构的增强:JDK 16增强了并发数据结构,引入了一些新的接口和类,例如StampedLock和VarHandle。
4.1optional类
Optional类是Java 8中引入的一个容器类,它可以用来包装一个可能为null的值。Optional类提供了一些方法来处理包装值的情况,例如判断值是否存在、获取值、如果值存在则执行某个操作等。
Optional类的主要特点是:
- 可以用来包装值,可以是任意类型的值,包括基本类型和引用类型。
- 可以通过isPresent()方法判断包装的值是否存在。
- 可以通过get()方法获取包装的值,但在获取值之前应该先通过isPresent()方法判断值是否存在。
- 可以通过orElse(T other)方法在包装的值不存在时返回一个默认值。
- 可以通过ifPresent(Consumer<? super T> action)方法在包装的值存在时执行某个操作。
使用Optional类可以避免使用null引发的空指针异常。当一个方法的返回值可能为null时,可以使用Optional类来包装返回值,这样调用该方法的代码就不用再判断返回值是否为null了。
下面是一个示例代码:
Optional<String> maybeNull = Optional.ofNullable(getValue()); if (maybeNull.isPresent()) {String value = maybeNull.get();System.out.println("Value is: " + value); } else {System.out.println("Value is null"); }// 利用ifPresent方法执行某个操作 maybeNull.ifPresent(v -> System.out.println("Value is: " + v));// 利用orElse方法给一个默认值 String value = maybeNull.orElse("default value"); System.out.println("Value is: " + value);
在上面的示例代码中,我们使用Optional类来包装一个可能为null的值。首先通过ofNullable方法将值包装成Optional对象,然后可以通过isPresent方法判断值是否存在。如果值存在,可以通过get方法获取值,或者利用ifPresent方法执行某个操作。如果值不存在,可以通过orElse方法返回一个默认值。