当前位置: 首页 > news >正文

Java Stream流详解:用法与常用API实战

1. 什么是Stream流?

Java 8 引入了 Stream API,它提供了一种高效、声明式的方式来处理集合数据。Stream 不是数据结构,而是对数据源(如集合、数组等)进行高效聚合操作(如过滤、映射、排序等)的工具。

Stream 的特点:

  • 不存储数据:Stream 本身不存储元素,它只是从数据源(如集合)获取数据并进行操作。

  • 不修改源数据:Stream 的操作不会改变原始数据源,而是生成新的流。

  • 惰性执行:许多 Stream 操作(如 filtermap)是惰性的,只有在终端操作(如 collectforEach)触发时才会执行。

  • 可并行化:Stream 可以轻松转换为并行流(parallelStream),以利用多核 CPU 提升性能。


2. Stream 的创建方式

Stream 可以通过多种方式创建:

(1)从集合创建

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
Stream<String> stream = names.stream();  // 顺序流
Stream<String> parallelStream = names.parallelStream();  // 并行流

(2)从数组创建

String[] languages = {"Java", "Python", "C++", "JavaScript"};
Stream<String> stream = Arrays.stream(languages);

(3)使用 Stream.of() 创建

Stream<Integer> numberStream = Stream.of(1, 2, 3, 4, 5);

(4)使用 Stream.generate() 或 Stream.iterate()

// 生成 5 个随机数
Stream<Double> randomNumbers = Stream.generate(Math::random).limit(5);// 生成 1, 3, 5, 7, 9(无限流,需要 limit 限制)
Stream<Integer> oddNumbers = Stream.iterate(1, n -> n + 2).limit(5);

3. Stream 常用 API 及案例

Stream 的操作分为 中间操作(Intermediate Operations) 和 终端操作(Terminal Operations)

(1)中间操作

① filter(Predicate<T>):过滤元素
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
List<String> longNames = names.stream().filter(name -> name.length() > 4)  // 只保留长度 >4 的名字.collect(Collectors.toList());  // 收集为 ListSystem.out.println(longNames);  // [Alice, Charlie, David]
② map(Function<T, R>):映射转换

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> squares = numbers.stream().map(n -> n * n)  // 计算平方.collect(Collectors.toList());System.out.println(squares);  // [1, 4, 9, 16, 25]
③ flatMap(Function<T, Stream<R>>):扁平化流
List<List<Integer>> nestedList = Arrays.asList(Arrays.asList(1, 2, 3),Arrays.asList(4, 5, 6)
);List<Integer> flatList = nestedList.stream().flatMap(List::stream)  // 将多个 List 合并为一个 Stream.collect(Collectors.toList());System.out.println(flatList);  // [1, 2, 3, 4, 5, 6]
④ sorted() / sorted(Comparator<T>):排序
List<String> names = Arrays.asList("Bob", "Alice", "David", "Charlie");
List<String> sortedNames = names.stream().sorted()  // 自然排序(字典序).collect(Collectors.toList());System.out.println(sortedNames);  // [Alice, Bob, Charlie, David]// 按长度排序
List<String> lengthSortedNames = names.stream().sorted(Comparator.comparingInt(String::length)).collect(Collectors.toList());System.out.println(lengthSortedNames);  // [Bob, Alice, David, Charlie]
⑤ distinct():去重
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 3, 4);
List<Integer> distinctNumbers = numbers.stream().distinct().collect(Collectors.toList());System.out.println(distinctNumbers);  // [1, 2, 3, 4]

(2)终端操作

① forEach(Consumer<T>):遍历
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream().forEach(System.out::println);
// 输出:
// Alice
// Bob
// Charlie
② collect(Collector<T, A, R>):收集结果
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
Set<String> nameSet = names.stream().collect(Collectors.toSet());Map<String, Integer> nameLengthMap = names.stream().collect(Collectors.toMap(name -> name,  // keyname -> name.length()  // value));System.out.println(nameSet);  // [Alice, Bob, Charlie]
System.out.println(nameLengthMap);  // {Alice=5, Bob=3, Charlie=7}
③ reduce(BinaryOperator<T>):归约
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream().reduce(0, (a, b) -> a + b);  // 计算总和System.out.println(sum);  // 15
④ count():计数
long count = Stream.of(1, 2, 3, 4, 5).count();
System.out.println(count);  // 5
⑤ anyMatch() / allMatch() / noneMatch():匹配检查
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);boolean hasEven = numbers.stream().anyMatch(n -> n % 2 == 0);  // 是否有偶数?
boolean allPositive = numbers.stream().allMatch(n -> n > 0);   // 是否全为正数?
boolean noneNegative = numbers.stream().noneMatch(n -> n < 0); // 是否没有负数?System.out.println(hasEven);      // true
System.out.println(allPositive);  // true
System.out.println(noneNegative); // true

4. 综合案例

案例1:统计员工薪资

List<Employee> employees = Arrays.asList(new Employee("Alice", 5000),new Employee("Bob", 6000),new Employee("Charlie", 7000)
);// 计算平均薪资
double avgSalary = employees.stream().mapToInt(Employee::getSalary)  // 转为 IntStream.average().orElse(0.0);System.out.println("平均薪资:" + avgSalary);

案例2:分组统计

List<String> words = Arrays.asList("apple", "banana", "cherry", "date", "elderberry");// 按单词长度分组
Map<Integer, List<String>> wordsByLength = words.stream().collect(Collectors.groupingBy(String::length));System.out.println(wordsByLength);
// 输出:{5=[apple], 6=[banana, cherry], 4=[date], 10=[elderberry]}

案例3:并行流加速计算

List<Integer> bigList = IntStream.range(1, 10_000_000).boxed().collect(Collectors.toList());long startTime = System.currentTimeMillis();
long sum = bigList.paralleltream()  // 并行流.mapToLong(Integer::longValue).sum();
long endTime = System.currentTimeMillis();System.out.println("总和:" + sum);
System.out.println("耗时:" + (endTime - startTime) + "ms");

5. 总结

  • Stream 提供了一种高效、声明式处理集合的方式,比传统的 for 循环更简洁。

  • 中间操作(如 filtermap)返回新的流,终端操作(如 collectforEach)触发计算。

  • 并行流parallelStream)可以加速大数据集处理。

  • 合理使用 mapfilterreduce 等操作,可以写出更优雅的代码。

http://www.dtcms.com/a/323491.html

相关文章:

  • Kotlin 协程线程切换机制详解
  • 规划是自动驾驶的“头脑”
  • 灰度测试(灰度发布、金丝雀发布)
  • 推荐系统学习笔记(十一)预估分数融合
  • leetcode-C语言-3479.水果成篮 III
  • C++ vector类
  • 3.2Vue Router路由导航
  • 【熵增与熵减:从混乱到有序的奥秘】
  • 词向量可视化:用TensorBoard或PCA探索词向量空间
  • 【JavaEE】(11) 前端基础三件套
  • 大数据与财务管理:未来就业的黄金赛道
  • java9学习笔记-part2
  • rosrun 和 roslaunch 区别
  • Busybox编译、制作initramfs,并在QEMU中运行
  • 医疗健康Agent:诊断辅助与患者管理的AI解决方案
  • rotary_emb 位置编码 加速
  • 练习uart和摄像头内核驱动开发测试
  • imx6ull-驱动开发篇15——linux自旋锁
  • 2025-08-09 李沐深度学习14——经典卷积神经网络 (2)
  • 【C++】模版进阶
  • redis存储原理与数据模型
  • 复数与频谱的联系
  • 库函数蜂鸣器的使用(STC8)
  • ECML PKDD 2025 | 时间序列(Time Series)论文总结
  • “秦时明月”提前布局商标被电视剧侵权!
  • 深入理解 RedisTemplate:简化 Java 与 Redis 的交互!
  • 【系统编程】进程创建
  • 本地进行语音文字互转
  • 国内外大模型体验与评测
  • Vue2 字段值映射通用方法