Java流(Stream)作为Java 8引入的核心特性之一,为集合操作提供了函数式编程的便捷方式,根据不同的分类标准,Java流可以从操作性质、数据源、并行处理模式及数据类型等多个维度进行划分,理解这些分类有助于更灵活地运用流处理数据。
按操作性质分类:中间操作与终止操作
这是Java流最核心的分类方式,直接关系到流的执行机制。
中间操作(Intermediate Operations)
中间操作是惰性执行的,它们不会立即处理数据,而是返回一个新的流,允许后续操作链式调用,常见的中间操作包括:
- 过滤型:如
filter(Predicate<T>),根据条件筛选元素,例如list.stream().filter(x -> x > 0)保留正数; - 转换型:如
map(Function<T, R>),将元素映射为其他类型,例如list.stream().map(String::length)获取字符串长度; - 排序型:如
sorted()或sorted(Comparator<T>),对流进行自然排序或自定义排序; - 去重型:如
distinct(),去除重复元素。
这些操作可以组合使用,形成操作链,直到遇到终止操作才会触发实际执行。
终止操作(Terminal Operations)
终止操作是及早执行的,它们触发流的处理并产生结果或副作用,常见的终止操作包括:
- 遍历型:如
forEach(Consumer<T>),对流中每个元素执行操作,例如打印元素; - 聚合型:如
collect(Collector<T, A, R>),将流元素收集到集合(如List、Set)或自定义容器中; - 归约型:如
reduce(BinaryOperator<T>),将流元素逐步合并为单个值,例如求和、求积; - 匹配型:如
anyMatch(Predicate<T>)、allMatch(Predicate<T>),判断流中是否存在或所有元素满足条件。
终止操作执行后,流会被关闭,无法再次使用。
按数据源分类:集合流、数组流、IO流等
Java流的数据来源多样,不同数据源决定了流的创建方式和处理场景。
集合流(Collection Stream)
最常用的流类型,通过集合的stream()或parallelStream()方法创建。
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream(); // 串行流
Stream<String> parallelStream = list.parallelStream(); // 并行流
数组流(Array Stream)
通过Arrays.stream(T[] array)方法将数组转换为流,支持处理基本类型数组(如int[])和对象数组。
int[] nums = {1, 2, 3};
IntStream intStream = Arrays.stream(nums); // 原始类型流
IO流(IO Stream)
通过BufferedReader.lines()将文件行转换为流,便于逐行处理文本文件。
try (BufferedReader reader = Files.newBufferedReader(Paths.get("file.txt"))) {
Stream<String> lines = reader.lines();
lines.forEach(System.out::println);
}
其他数据源
包括Stream.generate(Supplier<T>)生成无限流(如随机数)、Stream.iterate(T, UnaryOperator<T>)迭代生成流(如斐波那契数列)、Stream.of(T... values)从可变参数创建流等。
按并行与串行分类:并行流与串行流
根据处理模式,流可分为串行流和并行流,影响数据处理的效率和方式。
串行流(Sequential Stream)
默认模式,按单线程顺序处理元素,适合数据量小或操作逻辑简单场景。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); numbers.stream().map(x -> x * 2).forEach(System.out::println); // 顺序输出2, 4, 6, 8, 10
并行流(Parallel Stream)
通过parallelStream()或parallel()方法启用,利用Fork-Join框架将任务拆分为多个子任务并行处理,适合大数据量计算密集型场景。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); numbers.parallelStream().map(x -> x * 2).forEach(System.out::println); // 输出顺序不固定
需注意,并行流并非总是更快,线程切换、数据拆分开销可能抵消并行优势,且操作需保证线程安全(如避免共享可变状态)。
按数据类型分类:对象流与原始类型流
根据流中元素的数据类型,可分为对象流和原始类型流,后者专门为基本类型优化,避免装箱拆箱开销。
对象流(Stream
处理引用类型(如String、Integer),例如Stream<String>、Stream<User>。
原始类型流(Primitive Stream)
Java 8提供了三种原始类型流:IntStream(int)、LongStream(long)、DoubleStream(double),支持直接操作基本类型,提供更高效的数值计算方法(如sum()、average())。
IntStream intStream = IntStream.of(1, 2, 3); int sum = intStream.sum(); // 求和,无需装箱
Java流的分类从多个维度揭示了其设计逻辑:按操作性质区分惰性与及早执行,按数据源适配不同数据场景,按并行模式平衡效率与复杂度,按数据类型优化性能,合理选择流类型和操作方式,能显著提升代码的可读性和执行效率,是Java函数式编程的重要基础。



















