java8新特性-尚硅谷

发布时间 2023-12-13 10:54:24作者: 西芹-小汤圆

新特性简介

  • 速度更快,便于并行
  • 代码更少,增加了新的语法:Lambda表达式
  • 强大的Stream API
  • 最大化的减少空指针异常:Optional
  • Nashorn引擎,允许在JVM上运行JS应用

Lambda表达式

Lambda表达式的本质:与其他语言的lambda表达式不同,java中的lambda表达式不是匿名函数,而是作为函数式接口的实例。

(o1,02) -> Interger.compare(o1,o2)为例,->是Lambda操作符或箭头操作符,左边是形参列表,其实就是接口中的抽象方法的形参列表,右边是lambda体,其实就是重写的抽象方法的方法体。

以前使用匿名实现类表示的现在都可以用lambda表达式做。

语法格式

//1.无参,无返回值
Runnable r2 = () -> System.out.println("hello,world");
//2.Lambda需要一个参数,但是没有返回值
Consumer<String> con = (String s) -> {System.out.println(s);};
//3.数据类型可以省略,因为可由编译器推断得出,称为“类型推断”,只有一个参数时可以省略小括号
Consumer<String> con = s -> {System.out.println(s);};
//4.表达式需要两个或以上的参数,多条执行语句,并且可以有返回值
Comparator<Integer> com = (o1,o2) -> {
    System.out.println("========");
    return o1.compareTo(o2);
};
//5.当lambda题只有一条语句时,return和大括号都可以省略
Comparator<Integer> com = (o1,o2) -> o1.compareTo(o2);

函数式接口

如果一个接口中,只声明了一个抽象方法,则此接口就称为函数式接口。

我们可以在一个接口上使用@FunctionalInterface注解,这样可以检测它是否为函数式接口。

在java.util.function包下定义了java8丰富的函数式接口。

java不仅可以支持OOP(面向对象编程),还可以支持OOF(面向函数编程)。

核心函数式接口

接口 参数类型 返回类型 用途 方法
Consumer T void 对类型为T的对象应用操作 void accept(T t)
Supplier T 返回类型为T的对象 T get()
Function<T,R> T R 对类型为T的对象应用操作,并返回结果为R的对象 R apply(T t)
Predicate T boolean 确定类型为T的对象是否满足某种约束,并返回boolean值 boolean test(T t)

方法引用和构造器引用

当要传递给lambda体的操作,已经有实现的方法了,可以使用方法引用。方法引用就是lambda表达式,通过方法的名字来指向一个方法,可以认为是lambda表达式的一个语法糖。

使用的要求是实现接口的抽象对象方法的参数列表和返回值类,必须与方法引用的方法的参数列表和返回值类型一致。

使用格式:类或对象 :: 方法名。具体有三种情况,对象调用非静态方法,类调用静态方法,类调用非静态方法。

//Consumer中的void accept(T t)和PrintStream中的void println(T t)的参数列表和返回值类型一致
Consumer<String> con1 = s -> System.out.println(s);
con1.accept("hello,world");
//使用方法引用
PrintStream ps = System.out;
Consumer<String> con2 = ps::println;
con2.accept("hello,beijing");

//类::实例方法,Comparator中的int compare(T o1,T o2)和String中的int o1.compareTo(o2)
//前者比后者多一个参数,实际上是使用该参数调用实例方法,因为类是无法调用实例方法的
Comparator<String> com = (o1,o2) -> o1.compareTo(o2);
Comparator<String> com2 = String :: compareTo;

//构造器引用与方法引用类似
Supplier<Employee> sup = () -> new Employee();
Supplier<Employee> sup1 = Employee::new;

Stream API

Stream API把真正的函数式编程风格引入到java中。使用Stream API可以对集合数据进行操作,可以执行非常复杂的查找、过滤和映射数据等操作,这操作类似SQL执行的数据库查询。

现在数据库源有MongDB,Redis等,而这些NoSQL的数据就需要java层面去处理。

Stream和Collection集合的区别:Collection是一种静态的内存数据结构,而Stream是有关计算的。前者主要面向内存,存储在内存中,后者主要是面向CPU,通过CPU实现计算。

Stream自身不存储元素。Stream不会改变源对象,相反,他们会返回一个持有结果的新Stream。

Stream操作是延迟执行的,只有在执行终止操作,才执行中间操作链,并产生结果。执行终止操作后流不能再复用,若想继续操作需要重新创建新的Stream。

Optional类是一个容器类,可以保存类型T的值,代表这个值存在,或者仅仅保存null,表示这个值不存在。是java8中用于解决空指针异常引入的类。

创建Stream流

  • 集合可以通过stream()方法返回一个顺序流,通过parallelStream()方法返回一个并行流。
  • 数组可以通过stream()方法返回一个流。
  • 通过Stream的of()方法,在方法内填入多个参数形成容器。
  • 使用iterate()迭代方法和generate()生成方法创建无限流,主要用于生成数据。
List<Employee> employees = EmployeeData.getEmployees();//获取一个集合
//default Stream<E> stream():返回一个顺序流
Stream<Employee> stream = employees.stream();
Stream.of(1,2,3,4,6);//填入参数形成容器
//迭代方法,初始值为0,每次迭代加2,limit()限制输出个数,并在forEach()中指定输出位置
Stream.iterate(0,t -> t+2).limit(10)forEach(System.out::println);
Stream.generate(Math::random).limit(10)forEach(System.out::println);//生成10个随机数

中间操作

筛选与切片

方法 作用
fliter(Predicate p) 接收Lambda,从流中排除某些元素
distinct() 筛选,通过流所生成元素的hashCode()和equals()去除重复元素
limit(long maxSize) 截断流,使其元素不超过给定数量
skip(long n) 跳过元素,返回一个忽略前n个元素的流。若流中元素不足n个,则返回一个空流。

映射与排序

方法 作用
map(Function f) 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
mapToDouble(ToDoubleFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个DoubleStream。
mapToint(TointFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个IntStream。
mapToLong(ToLongFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个LongStream。
flatMap(Function f) 接收一个函数作为参数,将流中的每个值都转换成一个流,然后把所有流连接成一个流。例如将字符串数组的每个元素拆成字符,再组合成一个字符数组。
sorted(Comparator com) 产生一个新流,如果没有传入比较器,则按自然顺序排序,否则按照比较器顺序排序。

终止

map和reduce的连接通常被称为map-reduce模式,因Google用它来进行网络搜索而出名。

Collect接口中方法的实现决定了如果对流执行收集的操作,如收集到List,Set和Map。另外Collects实用类提供了很多静态方法,可以方便地创建常见收集器实例。

方法 作用
allMatch(Predicate p) 检查是否匹配所有元素
anyMatch(Predicate p) 检查是否至少匹配一个元素
noneMatch(Predicate p) 检查是否没有匹配所有元素
findFirst() 返回第一个元素
findAny() 返回当前流中所有元素
count() 返回流中元素的总个数
max(Comparator c) 返回流中元素的最大值
min(Comparator c) 返回流中的最小值
forEach(Consumer c) 内部迭代
reduce(T iden,BinaryOperator b) 可以将流中元素反复结合起来,得到一个值,返回T。
reduce(BinaryOperator b) 可以将流中元素反复结合起来,得到一个值,返回Optional
collect(Collector c) 将流转换为其他形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法