Stream API
Java 8 引入了 Stream API,它提供了一种高效且易于使用的方式来处理集合数据。Stream 是一种数据处理抽象,允许以声明性方式处理数据流。它支持顺序和并行操作。以下是 Stream API 的一些关键知识点和相应的示例代码,每行都包含中文注释。
1. Stream 的创建
Stream 可以通过集合、数组、I/O 操作等多种方式创建。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class StreamExample {
public static void main(String[] args) {
// 通过集合创建 Stream
List<String> list = Arrays.asList("a", "b", "c", "d");
Stream<String> streamFromList = list.stream(); // 从列表中创建流
// 通过数组创建 Stream
String[] array = {"e", "f", "g", "h"};
Stream<String> streamFromArray = Arrays.stream(array); // 从数组中创建流
// 通过 Stream 的静态方法创建 Stream
Stream<String> streamFromValues = Stream.of("i", "j", "k"); // 通过指定值创建流
}
}
2. 中间操作 (Intermediate Operations)
中间操作会返回一个新的 Stream,并不会立即执行,直到遇到终端操作才会执行。这些操作是惰性的。
常见的中间操作包括:
- filter: 过滤流中的元素。
- map: 对流中的每个元素应用函数。
- flatMap: 将流中的每个元素替换为一个新的流,然后合并这些流。
- sorted: 对流中的元素进行排序。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamIntermediateExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
// filter: 过滤出所有偶数
List<Integer> evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0) // 只保留偶数
.collect(Collectors.toList()); // 收集结果到列表
// map: 每个元素乘以2
List<Integer> doubledNumbers = numbers.stream()
.map(n -> n * 2) // 每个元素乘以2
.collect(Collectors.toList()); // 收集结果到列表
// sorted: 对流中的元素进行排序
List<Integer> sortedNumbers = numbers.stream()
.sorted((a, b) -> b - a) // 按降序排序
.collect(Collectors.toList()); // 收集结果到列表
}
}
3. 终端操作 (Terminal Operations)
终端操作会触发流的计算,返回一个结果或副作用,流在执行完终端操作后即被消耗,不能再次使用。
常见的终端操作包括:
- collect: 将流转换为其他形式,通常用于 List、Set 等集合。
- forEach: 遍历流中的每个元素并执行指定的操作。
- reduce: 将流中的元素组合为一个值。
- count: 计算流中元素的数量。
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class StreamTerminalExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
// forEach: 输出每个元素
numbers.stream()
.forEach(System.out::println); // 输出每个元素
// count: 统计流中元素的数量
long count = numbers.stream().count(); // 获取元素的数量
// reduce: 计算元素的和
Optional<Integer> sum = numbers.stream()
.reduce((a, b) -> a + b); // 将所有元素相加
}
}
4. 并行流 (Parallel Streams)
通过并行流,可以利用多核 CPU,提高数据处理速度。并行流会将数据划分成多个子流,并行处理。
import java.util.Arrays;
import java.util.List;
public class ParallelStreamExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
// 并行流: 对每个元素进行平方运算
numbers.parallelStream()
.map(n -> n * n) // 对每个元素求平方
.forEach(System.out::println); // 输出结果
}
}
5. Stream 的常用方法
- distinct: 去除流中的重复元素。
- limit: 获取流中的前 N 个元素。
- skip: 跳过流中的前 N 个元素。
- anyMatch: 检查是否存在任何一个元素符合条件。
import java.util.Arrays;
import java.util.List;
public class StreamMethodsExample {
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "apple", "orange", "banana");
// distinct: 去重
words.stream()
.distinct() // 去除重复元素
.forEach(System.out::println); // 输出结果
// limit: 获取前两个元素
words.stream()
.limit(2) // 只获取前两个元素
.forEach(System.out::println); // 输出结果
// skip: 跳过前两个元素
words.stream()
.skip(2) // 跳过前两个元素
.forEach(System.out::println); // 输出结果
// anyMatch: 是否有任何元素包含 "a"
boolean hasA = words.stream()
.anyMatch(word -> word.contains("a")); // 检查是否存在包含 "a" 的元素
}
}
总结
Java 8 的 Stream API 提供了强大的数据处理能力,通过链式操作,可以极大简化代码,并提高可读性。熟练掌握 Stream API 的使用,可以在开发中大幅提高效率。