Java Stream 是 Java 8 引入的一个重要的功能,它允许你以声明性的方式对集合或其他数据源进行操作。Stream 流提供了一种高效、易读且功能强大的方式来处理数据集合,支持顺序和并行两种处理方式。
// 从集合创建
List list = Arrays.asList("a", "b", "c");
Stream stream = list.stream();
// 从数组创建
String[] array = new String[]{"a", "b", "c"};
Stream streamFromArray = Arrays.stream(array);
// 使用静态方法 Stream.of()
Stream streamOf = Stream.of("a", "b", "c");
// filter() 方法用于筛选符合条件的元素
List numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
List evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
// evenNumbers 结果为 [2, 4, 6]
// map() 方法用于将流中的元素映射为另一种类型
List words = Arrays.asList("hello", "world", "java");
List lengths = words.stream()
.map(String::length)
.collect(Collectors.toList());
// lengths 结果为 [5, 5, 4]
// 使用 reduce() 进行聚合操作
List numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.reduce(0, (a, b) -> a + b);
// sum 结果为 15
// 使用收集器 Collectors 进行聚合
List numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.collect(Collectors.summingInt(n -> n));
// sum 结果为 15
// sorted() 方法对流中的元素进行排序
List numbers = Arrays.asList(5, 3, 2, 4, 1);
List sortedNumbers = numbers.stream()
.sorted()
.collect(Collectors.toList());
// sortedNumbers 结果为 [1, 2, 3, 4, 5]
// 自定义排序
List words = Arrays.asList("banana", "apple", "orange");
List sortedWords = words.stream()
.sorted((a, b) -> a.length() - b.length())
.collect(Collectors.toList());
// sortedWords 结果为 ["apple", "banana", "orange"]
// distinct() 方法用于去除重复的元素
List numbers = Arrays.asList(1, 2, 2, 3, 3, 3, 4);
List uniqueNumbers = numbers.stream()
.distinct()
.collect(Collectors.toList());
// uniqueNumbers 结果为 [1, 2, 3, 4]
// limit() 方法限制流中元素的数量
List numbers = Arrays.asList(1, 2, 3, 4, 5);
List limitedNumbers = numbers.stream()
.limit(3)
.collect(Collectors.toList());
// limitedNumbers 结果为 [1, 2, 3]
// skip() 方法跳过流中的前 n 个元素
List numbers = Arrays.asList(1, 2, 3, 4, 5);
List skippedNumbers = numbers.stream()
.skip(2)
.collect(Collectors.toList());
// skippedNumbers 结果为 [3, 4, 5]
// anyMatch() 检查是否至少有一个元素符合给定的条件
List words = Arrays.asList("hello", "world", "java");
boolean hasLongWord = words.stream()
.anyMatch(word -> word.length() > 5);
// hasLongWord 结果为 true
// allMatch() 检查所有元素是否都符合给定的条件
List numbers = Arrays.asList(2, 4, 6, 8);
boolean allEven = numbers.stream()
.allMatch(n -> n % 2 == 0);
// allEven 结果为 true
// noneMatch() 检查没有元素符合给定的条件
List numbers = Arrays.asList(1, 3, 5, 7);
boolean noneEven = numbers.stream()
.noneMatch(n -> n % 2 == 0);
// noneEven 结果为 true
// findFirst() 返回流中的第一个元素
List words = Arrays.asList("hello", "world", "java");
Optional firstWord = words.stream()
.findFirst();
// firstWord 结果为 Optional["hello"]
// findAny() 返回流中的任意一个元素(在并行流中可能更高效)
List words = Arrays.asList("hello", "world", "java");
Optional anyWord = words.stream()
.findAny();
// anyWord 结果可能为 Optional["hello"] 或其他元素
// flatMap() 将流中的每个元素映射为另一个流,然后将这些流连接成一个流
List> listOfLists = Arrays.asList(
Arrays.asList(1, 2),
Arrays.asList(3, 4),
Arrays.asList(5, 6)
);
List flatList = listOfLists.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
// flatList 结果为 [1, 2, 3, 4, 5, 6]
// 转换为 List
List numbers = Arrays.asList(1, 2, 3, 4, 5);
List squaredList = numbers.stream()
.map(n -> n * n)
.collect(Collectors.toList());
// squaredList 结果为 [1, 4, 9, 16, 25]
// 转换为 Set
List numbers = Arrays.asList(1, 2, 2, 3, 3, 3, 4);
Set uniqueSet = numbers.stream()
.collect(Collectors.toSet());
// uniqueSet 结果为 {1, 2, 3, 4}
// 转换为 Map
List words = Arrays.asList("hello", "world", "java");
Map wordLengthMap = words.stream()
.collect(Collectors.toMap(word -> word, word -> word.length()));
// wordLengthMap 结果为 {"hello"=5, "world"=5, "java"=4}
// 计算员工工资总和
List employees = Arrays.asList(
new Employee("Alice", 5000),
new Employee("Bob", 6000),
new Employee("Charlie", 7000)
);
int totalSalary = employees.stream()
.mapToInt(Employee::getSalary)
.sum();
// totalSalary 结果为 18000
// 找出最长的单词
List words = Arrays.asList("hello", "world", "java");
String longestWord = words.stream()
.max((a, b) -> a.length() - b.length())
.orElse("");
// longestWord 结果为 "hello"
// 使用函数式接口对数字进行平方操作
Function square = x -> x * x;
List numbers = Arrays.asList(1, 2, 3, 4, 5);
List squaredNumbers = numbers.stream()
.map(square)
.collect(Collectors.toList());
// squaredNumbers 结果为 [1, 4, 9, 16, 25]
// 不推荐:在 Stream 操作中修改外部变量
List numbers = Arrays.asList(1, 2, 3, 4, 5);
List squaredList = new ArrayList<>();
numbers.stream()
.forEach(n -> squaredList.add(n * n));
// squaredList 结果为 [1, 4, 9, 16, 25]
// 推荐:使用 map() 和 collect() 进行无副作用的操作
List squaredList = numbers.stream()
.map(n -> n * n)
.collect(Collectors.toList());
// Stream 操作是延迟执行的,只有在终止操作时才会真正执行
List numbers = Arrays.asList(1, 2, 3, 4, 5);
Stream stream = numbers.stream()
.filter(n -> n % 2 == 0);
// 此时还没有执行过滤操作
List evenNumbers = stream.collect(Collectors.toList());
// 此时才真正执行过滤操作
// 在 Stream 操作中处理异常
List words = Arrays.asList("hello", "world", "java");
List lengths = words.stream()
.map(word -> {
try {
return word.length();
} catch (Exception e) {
return 0;
}
})
.collect(Collectors.toList());
// Stream 只能使用一次,再次使用会抛出异常
List numbers = Arrays.asList(1, 2, 3, 4, 5);
Stream stream = numbers.stream();
stream.filter(n -> n % 2 == 0).collect(Collectors.toList());
// stream.filter(n -> n % 2 == 0).collect(Collectors.toList()); // 再次使用会抛出异常
// 并行流可以提高处理性能,但需要注意线程安全和顺序问题
List numbers = Arrays.asList(1, 2, 3, 4, 5);
List squaredList = numbers.parallelStream()
.map(n -> n * n)
.collect(Collectors.toList());
// squaredList 结果可能为 [1, 4, 9, 16, 25],但顺序可能不保证
// 对于简单操作,传统的循环可能更高效
List numbers = Arrays.asList(1, 2, 3, 4, 5);
// 不推荐:过度使用 Stream
List squaredList = numbers.stream()
.map(n -> n * n)
.collect(Collectors.toList());
// 推荐:对于简单操作,直接使用循环
List squaredList = new ArrayList<>();
for (int n : numbers) {
squaredList.add(n * n);
}
// 在 Stream 操作中处理可能的空值
List words = Arrays.asList("hello", null, "java");
List nonNullWords = words.stream()
.filter(Objects::nonNull)
.collect(Collectors.toList());
// nonNullWords 结果为 ["hello", "java"]
// 使用收集器时注意线程安全和性能问题
List numbers = Arrays.asList(1, 2, 3, 4, 5);
Map> partitionedMap = numbers.stream()
.collect(Collectors.partitioningBy(n -> n % 2 == 0));
// partitionedMap 结果为 {false=[1, 3, 5], true=[2, 4]}
// 中间操作不会执行任何处理,直到遇到终止操作
List numbers = Arrays.asList(1, 2, 3, 4, 5);
Stream stream = numbers.stream()
.filter(n -> n % 2 == 0);
// 此时还没有执行过滤操作
List evenNumbers = stream.collect(Collectors.toList());
// 此时才真正执行过滤操作
// Stream 操作不会修改源数据,除非显式地进行修改
List numbers = Arrays.asList(1, 2, 3, 4, 5);
List squaredList = numbers.stream()
.map(n -> n * n)
.collect(Collectors.toList());
// numbers 列表保持不变,squaredList 是新的列表
Java Stream 流提供了一种高效、易读且功能强大的方式来处理数据集合。通过筛选过滤、映射转换、聚合操作、排序、去重、限制和跳过、匹配和查找、流的扁平化以及转换为其他集合形式等常见用法,可以方便地对数据进行各种操作。在实际应用中,需要注意避免副作用、处理异常、注意延迟执行特性、避免过度使用 Stream 等事项,以确保代码的正确性和高效性。