321. Java Stream API - 使用 StringBuffer 收集原始类型流

0 阅读2分钟

321. Java Stream API - 使用 StringBuffer 收集原始类型流

JavaStream API 中,我们常常使用 Collectors.joining() 方法将对象流中的元素拼接成字符串,例如:

Stream.of("A", "B", "C").collect(Collectors.joining()); // 结果是 "ABC"

但这个方法只适用于对象流(如 Stream),无法直接用于 IntStreamLongStreamDoubleStream原始类型流


❓那如果我们想拼接一个 IntStream 怎么办?

由于 String 是不可变类,每次拼接字符串都会创建新的对象,性能低下。Java 推荐使用可变的字符串容器 —— StringBufferStringBuilder

这里我们将使用 StringBuffer 来拼接 IntStream 中的元素。


🔨 实现方式:手动构建 Collector

就像之前讲的,我们可以使用三个组件手动构建一个 collector,用于将 IntStream 拼接成一个字符串:

🧩 三个组件

Supplier<StringBuffer> supplier = StringBuffer::new;
ObjIntConsumer<StringBuffer> accumulator = StringBuffer::append;
BiConsumer<StringBuffer, StringBuffer> combiner = StringBuffer::append;
  • supplier:提供一个新的 StringBuffer 对象
  • accumulator:将每个 int 元素追加到 StringBuffer
  • combiner:并行流处理时合并多个 StringBuffer

✅ 示例代码

import java.util.function.*;
import java.util.stream.*;

public class PrimitiveJoinExample {
    public static void main(String[] args) {
        Supplier<StringBuffer> supplier = StringBuffer::new;
        ObjIntConsumer<StringBuffer> accumulator = StringBuffer::append;
        BiConsumer<StringBuffer, StringBuffer> combiner = StringBuffer::append;

        StringBuffer result = IntStream.range(0, 10)
                                       .collect(supplier, accumulator, combiner);

        System.out.println("collect = " + result);
    }
}

📦 输出结果:

collect = 0123456789

流中的每个整数依次被拼接成字符串,就像我们用 Collectors.joining() 处理字符串一样。


💬 延伸讲解

  • 为什么不能用 String? 因为 String 是不可变的,每次拼接都会生成一个新对象,效率低;
  • 为什么用 StringBuffer 而不是 StringBuilder StringBuffer 是线程安全的,在并行流中更可靠。但如果你确定是串行流,可以使用 StringBuilder 提升性能。

🧪 试试看并行流!

StringBuffer result = IntStream.range(0, 10)
                               .parallel()
                               .collect(supplier, accumulator, combiner);
System.out.println(result);

因为使用了线程安全的 StringBuffer,即使是并行流也能正确工作。


🎯 小结

目标实现方式
IntStream 拼接成字符串使用 StringBuffercollect(supplier, accumulator, combiner)
替代 Collectors.joining() 但适用于原始类型