java8新特性-尚硅谷
新特性简介#
- 速度更快,便于并行
- 代码更少,增加了新的语法: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
创建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
出处:https://www.cnblogs.com/xiqin-huang/p/17898576.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现