Java Stream 流创建的不同途径
Java Stream 流创建的不同途径
在 Java 编程领域,Stream API 为处理集合数据提供了一种高效且简洁的方式。Stream 允许以声明式的风格对数据集合进行操作,这使得代码更易读、易维护。而创建 Stream 流是使用 Stream API 的第一步,接下来我们将深入探讨 Java 中创建 Stream 流的不同途径。
通过集合创建 Stream
Java 中的 Collection
接口提供了两个方法来创建 Stream:stream()
和 parallelStream()
。stream()
方法返回一个顺序流,而 parallelStream()
方法返回一个并行流。
以下是通过 List
集合创建顺序流和并行流的示例代码:
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class CollectionStreamExample {
public static void main(String[] args) {
List<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Cherry");
// 创建顺序流
Stream<String> sequentialStream = fruits.stream();
sequentialStream.forEach(System.out::println);
// 创建并行流
Stream<String> parallelStream = fruits.parallelStream();
parallelStream.forEach(System.out::println);
}
}
在上述代码中,我们首先创建了一个 List
集合,并向其中添加了一些水果名称。然后,通过调用 stream()
方法创建了一个顺序流,并使用 forEach
方法打印出每个水果名称。接着,通过调用 parallelStream()
方法创建了一个并行流,并同样使用 forEach
方法打印出每个水果名称。
并行流利用多线程并行处理数据,在处理大数据集时能够显著提高性能。但需要注意的是,并行流在某些情况下可能会因为线程安全问题导致结果不准确,所以在使用并行流时要确保操作是线程安全的。
通过数组创建 Stream
Java 中的 Arrays
类提供了 stream
方法,可以将数组转换为 Stream。这种方式在处理数组数据时非常方便。
以下是通过数组创建 Stream 的示例代码:
import java.util.Arrays;
import java.util.stream.Stream;
public class ArrayStreamExample {
public static void main(String[] args) {
int[] numbers = {1, 2, 3, 4, 5};
// 将 int 数组转换为 IntStream
java.util.stream.IntStream intStream = Arrays.stream(numbers);
intStream.forEach(System.out::println);
String[] names = {"Alice", "Bob", "Charlie"};
// 将 String 数组转换为 Stream<String>
Stream<String> stringStream = Arrays.stream(names);
stringStream.forEach(System.out::println);
}
}
在上述代码中,我们首先定义了一个 int
数组和一个 String
数组。然后,分别使用 Arrays.stream
方法将它们转换为 IntStream
和 Stream<String>
,并通过 forEach
方法打印出数组中的每个元素。
Arrays.stream
方法还提供了重载版本,可以指定数组的起始索引和结束索引,从而只处理数组的部分元素。例如:
int[] numbers = {1, 2, 3, 4, 5};
java.util.stream.IntStream partialIntStream = Arrays.stream(numbers, 1, 4);
partialIntStream.forEach(System.out::println);
上述代码将只处理数组中索引从 1(包含)到 4(不包含)的元素,即 2、3、4。
使用 Stream.of 方法创建 Stream
Stream
类本身提供了 of
方法,可以直接创建一个包含指定元素的 Stream。这种方式适用于手动指定少量元素来创建 Stream 的场景。
以下是使用 Stream.of
方法创建 Stream 的示例代码:
import java.util.stream.Stream;
public class StreamOfExample {
public static void main(String[] args) {
// 创建包含字符串元素的 Stream
Stream<String> stringStream = Stream.of("Apple", "Banana", "Cherry");
stringStream.forEach(System.out::println);
// 创建包含整数元素的 Stream
Stream<Integer> integerStream = Stream.of(1, 2, 3);
integerStream.forEach(System.out::println);
}
}
在上述代码中,我们分别使用 Stream.of
方法创建了包含字符串和整数元素的 Stream,并通过 forEach
方法打印出每个元素。
Stream.of
方法还支持可变参数,这意味着可以传入任意数量的同类型元素来创建 Stream。
使用 Stream.generate 方法创建无限 Stream
Stream.generate
方法用于创建一个无限长度的 Stream,它接受一个 Supplier
作为参数,Supplier
会不断提供新的元素。
以下是使用 Stream.generate
方法创建无限 Stream 的示例代码:
import java.util.Random;
import java.util.stream.Stream;
public class StreamGenerateExample {
public static void main(String[] args) {
// 创建一个无限的随机数 Stream
Stream<Double> randomStream = Stream.generate(() -> new Random().nextDouble());
randomStream.limit(5).forEach(System.out::println);
}
}
在上述代码中,我们使用 Stream.generate
方法创建了一个无限的随机数 Stream。由于这是一个无限流,我们使用 limit
方法限制只取前 5 个元素并打印出来。
Stream.generate
方法适用于需要生成大量数据的场景,但需要注意合理使用 limit
等方法来避免无限循环。
使用 Stream.iterate 方法创建无限 Stream
Stream.iterate
方法也用于创建无限长度的 Stream,它接受一个初始值和一个 UnaryOperator
作为参数。UnaryOperator
会对前一个元素进行操作,生成下一个元素。
以下是使用 Stream.iterate
方法创建无限 Stream 的示例代码:
import java.util.stream.Stream;
public class StreamIterateExample {
public static void main(String[] args) {
// 创建一个从 0 开始,每次加 2 的无限 Stream
Stream<Integer> integerStream = Stream.iterate(0, n -> n + 2);
integerStream.limit(5).forEach(System.out::println);
}
}
在上述代码中,我们使用 Stream.iterate
方法创建了一个从 0 开始,每次增加 2 的无限 Stream。同样,我们使用 limit
方法限制只取前 5 个元素并打印出来。
Stream.iterate
方法在生成有规律的序列数据时非常有用,比如等差数列、等比数列等。
使用 BufferedReader.lines 方法创建 Stream
BufferedReader
类的 lines
方法可以将文本文件的每一行作为一个元素创建成 Stream。这在处理文本文件时非常便捷。
以下是使用 BufferedReader.lines
方法创建 Stream 的示例代码:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.stream.Stream;
public class BufferedReaderStreamExample {
public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("example.txt"))) {
Stream<String> linesStream = reader.lines();
linesStream.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
}
}
在上述代码中,我们假设当前目录下有一个名为 example.txt
的文本文件。通过 BufferedReader
读取文件,并使用 lines
方法将文件的每一行转换为 Stream 中的一个元素,然后通过 forEach
方法打印出每一行。
需要注意的是,在使用 BufferedReader
时,要确保正确处理文件读取过程中可能出现的 IOException
。
使用 Pattern.splitAsStream 方法创建 Stream
Pattern
类的 splitAsStream
方法可以根据指定的正则表达式将字符串分割成多个部分,并创建成 Stream。
以下是使用 Pattern.splitAsStream
方法创建 Stream 的示例代码:
import java.util.regex.Pattern;
import java.util.stream.Stream;
public class PatternSplitStreamExample {
public static void main(String[] args) {
String sentence = "Hello, world! How are you?";
Pattern pattern = Pattern.compile("\\W+");
Stream<String> wordsStream = pattern.splitAsStream(sentence);
wordsStream.forEach(System.out::println);
}
}
在上述代码中,我们定义了一个字符串 sentence
,并使用 Pattern.compile
方法创建了一个以非单词字符(\\W+
)为分隔符的 Pattern
对象。然后,通过 splitAsStream
方法将字符串分割成多个单词,并创建成 Stream,最后通过 forEach
方法打印出每个单词。
这种方式在处理文本分词等场景下非常实用。
使用 IntStream.range 和 IntStream.rangeClosed 方法创建 IntStream
IntStream
类提供了 range
和 rangeClosed
方法来创建 IntStream
。range
方法生成的 IntStream
包含起始值但不包含结束值,而 rangeClosed
方法生成的 IntStream
包含起始值和结束值。
以下是使用这两个方法创建 IntStream
的示例代码:
import java.util.stream.IntStream;
public class IntStreamRangeExample {
public static void main(String[] args) {
// 创建一个从 0 到 4 的 IntStream(不包含 5)
IntStream rangeStream = IntStream.range(0, 5);
rangeStream.forEach(System.out::println);
// 创建一个从 0 到 5 的 IntStream(包含 5)
IntStream rangeClosedStream = IntStream.rangeClosed(0, 5);
rangeClosedStream.forEach(System.out::println);
}
}
在上述代码中,我们分别使用 IntStream.range
和 IntStream.rangeClosed
方法创建了两个不同范围的 IntStream
,并通过 forEach
方法打印出每个整数。
这两个方法在需要生成连续整数序列的场景中经常使用,比如循环计数等。
通过以上多种途径,我们可以根据不同的需求灵活地创建 Java Stream 流,从而更高效地处理数据集合。每种创建方式都有其适用场景,在实际编程中需要根据具体情况选择合适的方式。希望通过本文的介绍,你对 Java Stream 流的创建有了更深入的理解和掌握。