MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Java Stream 流创建的不同途径

2024-12-075.6k 阅读

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 方法将它们转换为 IntStreamStream<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 类提供了 rangerangeClosed 方法来创建 IntStreamrange 方法生成的 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.rangeIntStream.rangeClosed 方法创建了两个不同范围的 IntStream,并通过 forEach 方法打印出每个整数。

这两个方法在需要生成连续整数序列的场景中经常使用,比如循环计数等。

通过以上多种途径,我们可以根据不同的需求灵活地创建 Java Stream 流,从而更高效地处理数据集合。每种创建方式都有其适用场景,在实际编程中需要根据具体情况选择合适的方式。希望通过本文的介绍,你对 Java Stream 流的创建有了更深入的理解和掌握。