原文: https://beginnersbook.com/2017/10/java-8-stream-tutorial/
在上一个教程中,我们学习了 java 8 中的接口更改。在本指南中,我们将讨论流 API,这是 java 8 的另一个新功能。该 API 的所有类和接口都在java.util.stream
包中。通过使用流,我们可以对从集合,数组,输入/输出操作返回的数据执行各种聚合操作。在我们看到如何在 Java 中使用流 API 之前,让我们看一个例子来理解流的使用。
Java 流示例
要了解流的工作原理,让我们在不使用流的情况下进行示例,然后我们将看到与流相同的示例。
在不使用流的情况下查找某些字符串
import java.util.ArrayList;
import java.util.List;
public class Example{
public static void main(String[] args) {
List<String> names = new ArrayList<String>();
names.add("Ajeet");
names.add("Negan");
names.add("Aditya");
names.add("Steve");
int count = 0;
for (String str : names) {
if (str.length() < 6)
count++;
}
System.out.println("There are "+count+" strings with length less than 6");
}
}
输出:
There are 3 strings with length less than 6
使用流的相同示例
import java.util.ArrayList;
import java.util.List;
public class Example{
public static void main(String[] args) {
List<String> names = new ArrayList<String>();
names.add("Ajeet");
names.add("Negan");
names.add("Aditya");
names.add("Steve");
//Using Stream and Lambda expression
long count = names.stream().filter(str->str.length()<6).count();
System.out.println("There are "+count+" strings with length less than 6");
}
}
输出:
There are 3 strings with length less than 6
这些代码有什么区别?
两个示例的输出都是相同的,但是如果考虑代码的性能,这些示例之间会有很大的不同。
在第一个例子中,我们迭代整个列表以找到长度小于 6 的字符串。此代码中没有并行性。
在第二个例子中,stream()
方法返回所有名称的流,filter()
方法返回另一个长度小于 6 的名称流,count()
方法减少了这个流到结果。所有这些操作都是并行发生的,这意味着我们能够在流的帮助下并行化代码。 使用流并行执行操作比不使用流的顺序执行更快。
如何在 Java 中使用流
正如我们在上面的例子中看到的那样,流的工作可以分三个阶段来解释:
创建一个流
在初始流上执行中间操作,将其转换为另一个流,依此类推进一步的中间操作。在上面的例子中,
filter()
操作是中间操作,可以有多个中间操作。在最终流上执行端子操作以获得结果。在上面的例子中,
count()
操作是终端操作。
Java 流函数
流不存储元素。它只是执行聚合操作(例如我们在上面的例子中看到的
filter()
和count()
)来获得所需的数据流。我们对集合,数组或任何其他数据源执行的聚合操作不会更改源的数据,它们只返回一个新流。例如,我们上面看到的代码是使用流操作过滤长度小于 6 的字符串,但它没有更改列表的元素。
所有流操作本质上都是懒惰,这意味着它们在需要之前不会被执行。例如,如果我们想要使用流仅显示列表的前 2 个元素,则在显示列表的第二个元素之后,流操作将在第二次迭代结束时停止。
让我们看几个 Java 流的例子:
Java 流示例 1:迭代并显示选定的整数
import java.util.stream.*;
public class Example {
public static void main(String[] args){
Stream.iterate(1, count->count+1)
.filter(number->number%3==0)
.limit(6)
.forEach(System.out::println);
}
}
输出:
3
6
9
12
15
18
Java 流示例 2:连接两个流
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class Example {
public static void main(String[] args) {
//list 1
List<String> alphabets = Arrays.asList("A","B","C");
//list 2
List<String> names = Arrays.asList("Sansa","Jon","Arya");
//creating two streams from the two lists and concatenating them into one
Stream<String> opstream = Stream.concat(alphabets.stream(), names.stream());
//displaying the elements of the concatenated stream
opstream.forEach(str->System.out.print(str+" "));
}
}
输出:
A B C Sansa Jon Arya