基于本文回答
0
评论

在 Java中,常见的创建 Stream 的方式有哪些?

在 Java 中,创建 Stream(流)的方法非常多样,可以根据不同的数据源(集合、数组、I/O 通道、产生器等)来选择。

以下是 Java 中最常见的几种创建 Stream 的方式:


1. 通过集合(Collection)创建(最常用)

Java 的 Collection 接口在 Java 8 中新增了 stream()parallelStream() 方法,几乎所有的集合类(如 ListSet)都可以直接调用这两个方法来创建流。

  • stream():创建一个顺序流。
  • parallelStream():创建一个并行流(多线程处理)。
java
List<String> list = Arrays.asList("Apple", "Banana", "Orange");

// 1. 创建顺序流
Stream<String> stream = list.stream();

// 2. 创建并行流
Stream<String> parallelStream = list.parallelStream();

2. 通过数组创建

可以使用 Arrays.stream() 静态方法,或者使用 Stream.of() 方法将数组转化为流。

java
String[] array = {"Java", "Python", "C++"};

// 1. 使用 Arrays.stream()
Stream<String> stream1 = Arrays.stream(array);

// 2. 也可以指定范围 (前闭后开区间:[1, 3))
Stream<String> streamSub = Arrays.stream(array, 1, 3);

3. 通过 Stream 类的静态工厂方法

Stream 接口自身提供了几个静态方法,用于直接生成流。

Stream.of(T... values)

直接传入零个或多个元素。

java
Stream<String> stream = Stream.of("a", "b", "c");

Stream.empty()

创建一个空的流。通常用于避免返回 null

java
Stream<Object> emptyStream = Stream.empty();

Stream.builder()

使用构建器模式(Builder Pattern)一步步构建流,适用于动态添加元素的场景。

java
Stream<String> builtStream = Stream.<String>builder()
        .add("dog")
        .add("cat")
        .add("bird")
        .build();

4. 创建无限流(Infinite Streams)

无限流会源源不断地产生数据,通常需要配合 limit() 方法来截断,否则会无限循环。

Stream.generate(Supplier<T> s)

接受一个无参的供给型函数,用于生成无限个元素(常用于生成随机数、常量等)。

java
// 生成 5 个随机数并打印
Stream.generate(Math::random)
      .limit(5)
      .forEach(System.out::println);

Stream.iterate(T seed, UnaryOperator<T> f)

接受一个种子值(初始值)和迭代器函数,后一个元素基于前一个元素产生(如等差数列)。

java
// 从 0 开始,每次加 2,生成 5 个数:0, 2, 4, 6, 8
Stream.iterate(0, n -> n + 2)
      .limit(5)
      .forEach(System.out::println);

// Java 9 引入的重载版本,支持加入判断条件(类似于 for 循环)
Stream.iterate(0, n -> n < 10, n -> n + 2)
      .forEach(System.out::println); 

5. 创建基本折叠类型流(数值流)

为了避免装箱和拆箱的性能开销,Java 提供了三个特化版的数值流:IntStreamLongStreamDoubleStream

它们有自己独有的创建方式:

java
// 1. 包含 1, 2, 3
IntStream intStream = IntStream.of(1, 2, 3);

// 2. range(): 范围 [1, 5) ── 输出 1, 2, 3, 4
IntStream range = IntStream.range(1, 5);

// 3. rangeClosed(): 范围 [1, 5] ── 输出 1, 2, 3, 4, 5
IntStream rangeClosed = IntStream.rangeClosed(1, 5);

6. 通过 I/O 文件操作创建

Java 的 java.nio.file.Files 类提供了许多方法,可以直接将文件内容、目录信息等转换为流。

注意:这类流通常持有底层资源,建议使用 try-with-resources 自动关闭流。

① 按行读取文件 Files.lines()

java
Path path = Paths.get("data.txt");
try (Stream<String> lines = Files.lines(path, StandardCharsets.UTF_8)) {
    lines.forEach(System.out::println);
} catch (IOException e) {
    e.printStackTrace();
}

② 获取目录下的文件列表 Files.list()

java
try (Stream<Path> paths = Files.list(Paths.get("."))) {
    paths.forEach(System.out::println);
} catch (IOException e) {
    e.printStackTrace();
}

7. 其他 API 转换

许多 Java 常用类也专门提供了支持 Stream 的方法。

① 正则表达式 Pattern.splitAsStream()

将字符串按正则分割并直接转换为流。

java
Pattern pattern = Pattern.compile(",");
Stream<String> stream = pattern.splitAsStream("apple,banana,orange");

② 随机数流 Random.ints()

Random 类提供了生成随机数值流的方法。

java
new Random().ints(5) // 生成 5 个随机整数
            .forEach(System.out::println);

总结建议

  • 最常用Collection.stream()(处理已有集合)和 Stream.of()(临时测试)。
  • 处理数值:优先使用 IntStream / LongStream / DoubleStream 以提升性能。
  • 读取文件:优先使用 Files.lines(),性能优于传统逐行读取,且代码极其简洁。
右滑查看面试常问