java8新特性-尚硅谷-92


尚硅谷 Java 入门视频教程

# 新特性简介

  • 速度更快,便于并行
  • 代码更少,增加了新的语法: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 中元素做汇总的方法

文章作者: xiqin
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 xiqin !
  目录