# Java 8 流教程

> 原文： [https://beginnersbook.com/2017/10/java-8-stream-tutorial/](https://beginnersbook.com/2017/10/java-8-stream-tutorial/)

在上一个教程中，我们学习了 java 8 中的[接口更改。在本指南中，我们将讨论**流 API**，这是 **java 8** 的另一个新功能。该 API 的所有类和接口都在`java.util.stream`包中。通过使用流，我们可以对从集合，数组，输入/输出操作返回的数据执行各种聚合操作。在我们看到如何在 Java 中使用流 API 之前，让我们看一个例子来理解流的使用。](https://beginnersbook.com/2017/10/java-8-interface-changes-default-method-and-static-method/)

## Java 流示例

要了解流的工作原理，让我们在不使用流的情况下进行示例，然后我们将看到与流相同的示例。

**在不使用流**的情况下查找某些字符串

```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");
   }  
}
```

输出：

```java
There are 3 strings with length less than 6
```

**使用流**的相同示例

```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");

	//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");

   }  
}
```

输出：

```java
There are 3 strings with length less than 6
```

**这些代码有什么区别？**

两个示例的输出都是相同的，但是如果考虑代码的性能，这些示例之间会有很大的不同。
**在第一个例子**中，我们迭代整个列表以找到长度小于 6 的字符串。此代码中没有并行性。
**在第二个例子**中，`stream()`方法返回所有名称的流，`filter()`方法返回另一个长度小于 6 的名称流，`count()`方法减少了这个流到结果。所有这些操作都是并行发生的，这意味着我们能够在流的帮助下并行化代码。 **使用流并行执行操作比不使用流**的顺序执行更快。

## 如何在 Java 中使用流

正如我们在上面的例子中看到的那样，流的工作可以分三个阶段来解释：

1.  创建一个流

2.  在初始流上执行**中间操作**，将其转换为另一个流，依此类推进一步的中间操作。在上面的例子中，`filter()`操作是中间操作，可以有多个中间操作。

3.  在最终流上执行**端子操作**以获得结果。在上面的例子中，`count()`操作是终端操作。

## Java 流函数

1.  流**不存储**元素。它只是执行聚合操作（例如我们在上面的例子中看到的`filter()`和`count()`）来获得所需的数据流。

2.  我们对集合，数组或任何其他数据源**执行的聚合操作不会更改**源的数据，它们只返回一个新流。例如，我们上面看到的代码是使用流操作过滤长度小于 6 的字符串，但它没有更改列表的元素。

3.  所有流操作本质上都是**懒惰**，这意味着它们在需要之前不会被执行。例如，如果我们想要使用流仅显示列表的前 2 个元素，则在显示列表的第二个元素之后，流操作将在第二次迭代结束时停止。

让我们看几个 Java 流的例子：

## Java 流示例 1：迭代并显示选定的整数

```java
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);  
    }  
}
```

输出：

```java
3
6
9
12
15
18
```

## Java 流示例 2：连接两个流

```java
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+" "));
   }
}
```

输出：

```java
A B C Sansa Jon Arya
```

#### 相关文章：

1.  [Java 流`allMatch()`示例](https://beginnersbook.com/2017/11/java-8-stream-allmatch-example/)
2.  [Java 流`noneMatch()`示例](https://beginnersbook.com/2017/11/java-8-stream-nonematch-example/)
3.  [Java 流`anyMatch()`示例](https://beginnersbook.com/2017/11/java-8-stream-anymatch-example/)