java stream 流处理详解
stream 是 java 8 引入的一个强大的数据处理抽象,它允许你以声明式方式处理数据集合(类似于 sql 语句),支持并行操作,提高了代码的可读性和处理效率。
一、stream 的核心概念
1. 什么是 stream
- 不是数据结构:不存储数据,只是从数据源(集合、数组等)获取数据
- 函数式风格:支持 lambda 表达式和方法引用
- 延迟执行:许多操作(中间操作)不会立即执行,只有遇到终止操作才会执行
- 可消费性:stream 只能被消费一次,用完即失效
2. 操作类型
- 中间操作(intermediate operations):返回 stream 本身,可以链式调用(如 filter, map)
- 终止操作(terminal operations):产生最终结果或副作用(如 foreach, collect)
二、创建 stream 的多种方式
// 1. 从集合创建 list<string> list = arrays.aslist("a", "b", "c"); stream<string> stream1 = list.stream(); // 顺序流 stream<string> parallelstream = list.parallelstream(); // 并行流 // 2. 从数组创建 string[] array = {"a", "b", "c"}; stream<string> stream2 = arrays.stream(array); // 3. 使用stream.of() stream<string> stream3 = stream.of("a", "b", "c"); // 4. 使用stream.generate() 无限流 stream<double> randomstream = stream.generate(math::random).limit(5); // 5. 使用stream.iterate() 迭代流 stream<integer> iteratestream = stream.iterate(0, n -> n + 2).limit(10);
三、常用的中间操作
1. 过滤操作
// filter(predicate) 过滤符合条件的元素 list<string> filtered = list.stream() .filter(s -> s.startswith("a")) .collect(collectors.tolist());
2. 映射操作
// map(function) 将元素转换为其他形式 list<integer> lengths = list.stream() .map(string::length) .collect(collectors.tolist()); // flatmap 将多个流合并为一个流 list<string> flatmapped = list.stream() .flatmap(s -> stream.of(s.split(""))) .collect(collectors.tolist());
3. 去重和排序
// distinct() 去重 list<string> distinct = list.stream().distinct().collect(collectors.tolist()); // sorted() 自然排序 list<string> sorted = list.stream().sorted().collect(collectors.tolist()); // sorted(comparator) 自定义排序 list<string> customsorted = list.stream() .sorted((s1, s2) -> s2.compareto(s1)) .collect(collectors.tolist());
4. 其他中间操作
// limit(long) 限制元素数量 // skip(long) 跳过前n个元素 // peek(consumer) 查看流中元素(主要用于调试)
四、常用的终止操作
1. 遍历操作
// foreach(consumer) 遍历每个元素 list.stream().foreach(system.out::println);
2. 收集结果
// collect(collector) 将流转换为集合或其他形式 list<string> collectedlist = stream.collect(collectors.tolist()); set<string> collectedset = stream.collect(collectors.toset()); map<string, integer> map = stream.collect( collectors.tomap(function.identity(), string::length));
3. 聚合操作
// count() 计数 long count = list.stream().count(); // max/min(comparator) 最大/最小值 optional<string> max = list.stream().max(comparator.naturalorder()); // reduce 归约操作 optional<integer> sum = stream.of(1, 2, 3).reduce(integer::sum);
4. 匹配操作
// anymatch 任意元素匹配 boolean anystartswitha = list.stream().anymatch(s -> s.startswith("a")); // allmatch 所有元素匹配 boolean allstartswitha = list.stream().allmatch(s -> s.startswith("a")); // nonematch 没有元素匹配 boolean nonestartswithz = list.stream().nonematch(s -> s.startswith("z"));
五、数值流特化
java 8 提供了专门的数值流,避免装箱拆箱开销:
// intstream, longstream, doublestream intstream intstream = intstream.range(1, 100); // 1-99 doublestream doublestream = doublestream.of(1.1, 2.2); // 常用数值操作 int sum = intstream.rangeclosed(1, 100).sum(); // 1-100的和 optionaldouble avg = intstream.of(1, 2, 3).average();
六、并行流处理
// 创建并行流 list<string> parallelprocessed = list.parallelstream() .filter(s -> s.length() > 1) .collect(collectors.tolist()); // 注意事项: // 1. 确保操作是线程安全的 // 2. 避免有状态的操作 // 3. 数据量足够大时才使用并行流
七、收集器(collectors)的高级用法
// 分组 map<integer, list<string>> groupbylength = list.stream() .collect(collectors.groupingby(string::length)); // 分区 map<boolean, list<string>> partition = list.stream() .collect(collectors.partitioningby(s -> s.startswith("a"))); // 连接字符串 string joined = list.stream().collect(collectors.joining(", ")); // 汇总统计 intsummarystatistics stats = list.stream() .collect(collectors.summarizingint(string::length));
八、实际应用示例
示例1:处理对象集合
list<person> people = ...; // 获取所有成年人的姓名列表 list<string> adultnames = people.stream() .filter(p -> p.getage() >= 18) .map(person::getname) .collect(collectors.tolist()); // 按城市分组 map<string, list<person>> bycity = people.stream() .collect(collectors.groupingby(person::getcity)); // 计算每个城市的平均年龄 map<string, double> avgagebycity = people.stream() .collect(collectors.groupingby( person::getcity, collectors.averagingint(person::getage) ));
示例2:文件处理
// 读取文件并处理 try (stream<string> lines = files.lines(paths.get("data.txt"))) { long wordcount = lines .flatmap(line -> arrays.stream(line.split("\\s+"))) .filter(word -> word.length() > 0) .count(); } catch (ioexception e) { e.printstacktrace(); }
九、注意事项
- 流只能消费一次:尝试第二次使用已关闭的流会抛出
illegalstateexception
- 避免修改源数据:流操作期间不应修改源集合
- 合理使用并行流:并非所有情况都适合并行,小数据量可能适得其反
- 注意自动装箱:数值操作尽量使用原始类型特化流(intstream等)
- 延迟执行特性:没有终止操作,中间操作不会执行
stream api 提供了一种高效、声明式的数据处理方式,是现代 java 编程中不可或缺的工具。合理使用可以大幅提升代码的可读性和维护性。
到此这篇关于java的stream流处理的文章就介绍到这了,更多相关java stream流内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论