如何学习Java Stream API [+5 资源]
java中的流是可以执行顺序或并行操作的元素序列。
可以有“n”个中间操作,最后是一个终端操作,之后返回结果。
什么是流?
流可以由java 8中引入的stream api管理。
想象一下流就像一个制造流水线,其中一些商品需要制造、排序,然后打包发货。在java中,这些商品是对象或对象的集合,操作是制造、排序和打包,而流就是流水线。
流的组成部分有:
- 初始输入
- 中间操作
- 终端操作
- 最终结果
让我们探索一下java中流的一些特点:
- 流不是内存中的数据结构;相反,它是一系列数组、对象或对象的集合,由某些方法操作。
- 流具有声明性,即你指定要做什么,而不是如何做。
- 它们只能被消耗一次,因为它们不会被存储在任何地方。
- 流不会修改原始数据结构;它只会从原始数据结构中派生一个新的结构。
- 它返回从流水线中的最终方法派生的最终结果。
stream api与集合处理
集合是一种内存中的数据结构,用于存储和处理数据。集合提供了诸如set、map、list等数据结构来存储数据。另一方面,流是一种在处理数据后高效传输数据的方式。
下面是一个arraylist集合的例子:
import java.util.arraylist;
public class main {
public static void main(string[] args) {
arraylist list = new arraylist();
list.add(0, 3);
system.out.println(list);
}
}
输出:
[3]
如上例所示,您可以创建一个arraylist集合,将数据存储在其中,然后使用不同的方法对该数据进行操作。
使用流,您可以对现有的数据结构进行操作并返回一个新的修改后的值。下面是一个创建arraylist集合并使用流进行筛选的示例。
import java.util.arraylist;
import java.util.stream.stream;
public class main {
public static void main(string[] args) {
arraylist list = new arraylist();
for (int i = 0; i < 20; i++) {
list.add(i+1);
}
system.out.println(list);
stream filtered = list.stream().filter(num -> num > 10);
filtered.foreach(num -> system.out.println(num + " "));
}
}
输出
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
11
12
13
14
15
16
17
18
19
20
在上面的示例中,使用现有的list
创建了一个流,并对列表进行迭代以筛选大于10的值。请注意,流不存储任何内容,只是对列表进行迭代,并打印结果。如果尝试打印流,您将得到流的引用而不是值。
使用java stream api
java stream api接受一个元素源集合或元素序列,然后对它们执行操作以得到最终结果。流只是一个管道,通过这个管道流经并以某种方式转换的元素序列。
可以从各种源创建流,包括:
- 集合,如list或set。
- 数组。
- 使用缓冲区从文件及其路径中创建。
在流中执行两种类型的操作:
- 中间操作
- 终端操作
中间操作 vs. 终端操作
每个中间操作在内部返回一个新的流,该流使用指定的方法变换输入。实际上没有遍历任何东西;相反,它被传递到下一个流中。只有在终端操作中,流才会被遍历以获得所需的结果。
例如,假设你有一个包含10个数字的列表,你想要筛选出并映射到其他内容。不会立即遍历列表的每个元素以获取筛选结果并将其映射到其他内容。相反,会检查每个单独的元素,如果满足条件,则进行映射。为每个元素创建新的流。
map操作将在满足过滤条件的各个项上执行,而不是整个列表。在终端操作时,它们被遍历并组合成单个结果。
执行终端操作后,流将被消耗,不能再被进一步使用。必须创建一个新的流来执行相同的操作。
![](/wp-content/uploads/2023/09/06/qfxulwsv04a.jpg)
对于流的工作原理有一个表面级的理解后,让我们深入了解java中流的实现细节。
#1. 一个空流
使用stream api的empty
方法创建一个空流。
import java.util.stream.stream;
public class main {
public static void main(string[] args) {
stream emptystream = stream.empty();
system.out.println(emptystream.count());
}
}
#输出
0
在这里,如果打印此流中的元素数量,输出将为0,因为它是一个没有元素的空流。空流在避免空指针异常方面非常有帮助。
#2. 从集合创建流
集合,如list和set,公开了一个stream()
方法,允许你从集合创建一个流。然后可以遍历创建的流以获得最终结果。
arraylist list = new arraylist();
for (int i = 0; i < 20; i++) {
list.add(i+1);
}
system.out.println(list);
stream filtered = list.stream().filter(num -> num > 10);
filtered.foreach(num -> system.out.println(num + " "));
#输出
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
11
12
13
14
15
16
17
18
19
20
#3. 从数组创建流
arrays.stream()
方法用于从数组创建流。
import java.util.arrays;
public class main {
public static void main(string[] args) {
string[] stringarray = new string[]{"this", "is", "yaoweibin"};
arrays.stream(stringarray).foreach(item -> system.out.print(item + " "));
}
}
#output
this is yaoweibin
您还可以指定元素的起始和结束索引来创建流。起始索引是包含的,而结束索引是排除的。
string[] stringarray = new string[]{"this", "is", "yaoweibin"};
arrays.stream(stringarray, 1, 3).foreach(item -> system.out.print(item + " "));
#output
this is yaoweibin
#4. 使用流查找最小和最大数字
通过使用java中的比较器,可以访问集合或数组的最大和最小数字。 min()
和 max()
方法接受一个比较器并返回一个 optional 对象。
optional 对象是一个容器对象,可能包含非空值,也可能不包含。如果它包含非空值,在其上调用 get()
方法将返回该值。
import java.util.arrays;
import java.util.optional;
public class minmax {
public static void main(string[] args) {
integer[] numbers = new integer[]{21, 82, 41, 9, 62, 3, 11};
optional maxvalue = arrays.stream(numbers).max(integer::compare);
system.out.println(maxvalue.get());
optional minvalue = arrays.stream(numbers).min(integer::compare);
system.out.println(minvalue.get());
}
}
#output
82
3
学习资源
现在您对java中的流有了基本的了解,这里有5个资源可以帮助您熟悉java 8:
#1. java 8 in action
这本书是一个指南,展示了java 8的新功能,包括流、lambda和函数式编程风格。书中还包含了测验和知识检查问题,帮助您复习所学内容。
预览 | 产品 | 评级 | 价格 | |
---|---|---|---|---|
![]() |
java 8 in action: lambdas, streams, and functional-style programming | $42.77 | 在亚马逊上购买 |
您可以在亚马逊上以平装书和有声书的格式获取这本书。
#2. java 8 lambdas: 群众的函数式编程
本书专门设计用于教授核心java se开发人员如何添加lambda表达式以影响java语言。它包括清晰的解释,代码练习和示例,帮助您掌握java 8 lambda表达式。
预览 | 产品 | 评分 | 价格 | |
---|---|---|---|---|
![]() |
java 8 lambdas: 群众的函数式编程 | $18.60 | 在亚马逊上购买 |
它在亚马逊上提供平装书和kindle版本。
#3. java se 8 for the really impatient
如果您是一名经验丰富的java se开发人员,本书将指导您了解java se 8的改进、流api、添加的lambda表达式、java中并发编程的改进以及大多数人不了解的一些java 7特性。
预览 | 产品 | 评分 | 价格 | |
---|---|---|---|---|
![]() |
java se 8 for the really impatient | $8.02 | 在亚马逊上购买 |
它只在亚马逊上提供平装书格式。
#4. 使用lambda和流学习java函数式编程
![](/wp-content/uploads/2023/09/06/k4n5z1o0ncy.jpg)
这门由udemy提供的课程探讨了java 8和9中函数式编程的基本原理。lambda表达式、方法引用、流和函数接口是本课程关注的概念。
它还包括一系列与函数式编程相关的java谜题和练习。
#5. java类库
![](/wp-content/uploads/2023/09/06/32auurlztkp.jpg)
java类库是coursera提供的core java专项课程的一部分。它将教您如何使用java泛型编写类型安全的代码,了解由4000多个类组成的类库,如何处理文件和运行时错误。然而,参加此课程需要一些先决条件:
- java入门
- 使用java进行面向对象编程入门
- java中的面向对象层次结构
最后的话
java 8中的java stream api和lambda函数的引入简化和改进了java中的许多方面,例如并行迭代、函数式接口、代码量减少等。
然而,流有一些限制;它们最大的限制是它们只能被消费一次。如果您是java开发人员,上述资源可以帮助您更详细地了解这些主题,所以一定要查看它们。
您可能还想了解java中的异常处理。