当前位置: 技术文章>> Java 8 中的 Stream API 如何使用?

文章标题:Java 8 中的 Stream API 如何使用?
  • 文章分类: 后端
  • 7100 阅读

在Java 8中引入的Stream API无疑是对Java集合处理的一个重大革新,它提供了一种高效且表达力强的方式来处理数据集合(如List、Set)。Stream API 允许你以声明性方式处理数据集合,关注于“做什么”而非“怎么做”,从而提高了代码的可读性和可维护性。以下将深入探讨Java 8 Stream API的使用方法,通过实例展示其强大功能。

一、Stream API基础

Stream API的核心概念是流(Stream),它是对数据源(如集合)的一系列连续操作,这些操作包括过滤、映射、排序、归约等。流操作分为中间操作和终端操作:

  • 中间操作:返回流本身,可以链式调用多个中间操作。
  • 终端操作:产生结果或副作用,如forEach、collect、reduce等,之后流就不能再被使用了。

创建流

可以从集合、数组等数据源中创建流:

List<String> list = Arrays.asList("apple", "banana", "cherry");
Stream<String> stream = list.stream(); // 从集合创建流

String[] array = {"dog", "cat", "bird"};
Stream<String> arrayStream = Arrays.stream(array); // 从数组创建流

流的常用操作

1. 过滤(Filter)

过滤操作通过filter方法实现,它接受一个谓词(Predicate),返回所有符合该谓词的元素组成的流。

List<String> filtered = list.stream()
    .filter(s -> s.startsWith("a")) // 过滤以'a'开头的字符串
    .collect(Collectors.toList()); // 收集结果
2. 映射(Map)

映射操作通过map方法实现,它接受一个函数(Function),将流中的每个元素转换成另一种形式。

List<Integer> lengths = list.stream()
    .map(String::length) // 获取每个字符串的长度
    .collect(Collectors.toList());
3. 排序(Sorted)

对流中的元素进行排序,分为自然排序和自定义排序。

List<String> sorted = list.stream()
    .sorted() // 自然排序
    .collect(Collectors.toList());

// 自定义排序
List<Person> people = Arrays.asList(/* 假设这里有一些Person对象 */);
List<Person> sortedByAge = people.stream()
    .sorted(Comparator.comparingInt(Person::getAge))
    .collect(Collectors.toList());
4. 归约(Reduce)

归约操作通过reduce方法实现,它可以将流中的所有元素反复结合起来,得到一个值。

Optional<String> concatenated = list.stream()
    .reduce((s1, s2) -> s1 + "," + s2); // 将字符串用逗号连接

// 也可以使用reduce的另一种形式计算总和
int sum = list.stream()
    .mapToInt(String::length) // 将字符串映射为长度
    .sum(); // 直接求和
5. 收集(Collect)

收集操作通过collect方法实现,它可以将流中的元素收集到一个容器(如List、Set、Map)中,或者进行更复杂的归约操作。

List<String> collected = list.stream()
    .filter(s -> s.startsWith("a"))
    .collect(Collectors.toList()); // 收集到List中

// 收集到Map中
Map<Boolean, List<String>> partitioned = list.stream()
    .collect(Collectors.partitioningBy(s -> s.startsWith("a")));

二、Stream API的高级用法

除了上述基本操作外,Stream API还提供了一些高级用法,如并行流、复杂收集操作等。

并行流

并行流允许你利用多核处理器,对集合进行并行处理,从而提高性能。通过调用parallelStream()方法获取并行流。

List<Integer> numbers = Arrays.asList(/* 一些整数 */);
long sum = numbers.parallelStream()
    .mapToInt(Integer::intValue)
    .sum(); // 并行求和

注意,并非所有情况下并行流都比顺序流快,它取决于你的数据源大小、处理操作的复杂度以及你的硬件环境。

复杂收集操作

Collectors类提供了多种收集器(Collector),用于实现复杂的收集操作,如分组、分区、连接字符串等。

// 分组
Map<Integer, List<String>> groupedByLength = list.stream()
    .collect(Collectors.groupingBy(String::length));

// 分区(基于谓词)
Map<Boolean, List<String>> partitioned = list.stream()
    .collect(Collectors.partitioningBy(s -> s.startsWith("a")));

// 连接字符串
String joined = list.stream()
    .collect(Collectors.joining(", "));

三、实际应用场景

Stream API在数据处理、文件IO、数据库操作等多个领域都有广泛的应用。以下是一个简单的应用场景示例:

示例:处理学生成绩数据

假设你有一个学生成绩的数据集(List<StudentScore>),你需要筛选出所有成绩及格的学生,并按成绩从高到低排序,最后收集到一个列表中。

List<StudentScore> scores = /* 假设这里有一些StudentScore对象 */;

List<StudentScore> passingScores = scores.stream()
    .filter(score -> score.getScore() >= 60) // 筛选出成绩及格的学生
    .sorted(Comparator.comparingInt(StudentScore::getScore).reversed()) // 按成绩降序排序
    .collect(Collectors.toList()); // 收集到List中

// 打印结果
passingScores.forEach(score -> System.out.println(score));

四、总结

Java 8的Stream API为集合处理提供了一种全新的、声明式的编程模型,极大地提高了代码的可读性和可维护性。通过掌握Stream API的基本操作和高级用法,你可以更高效地处理数据集合,编写出更加简洁、优雅的代码。在实际开发中,不妨多尝试使用Stream API来替代传统的集合遍历和条件判断,相信你会爱上这种编程方式。

在探索Stream API的过程中,不妨关注“码小课”网站,这里不仅有丰富的Java教程和实例,还有来自社区的宝贵经验和最佳实践分享,帮助你更深入地理解和掌握Java 8及其新特性。