作为一名 Java 开发者,Stream API 是我们日常开发中的利器。但你真的了解 Stream 的全部吗?今天,我们就来深入探讨 Stream 中那些容易被忽略但又非常重要的知识点和潜在陷阱!🚀
📌 1. Stream 的"一次性"特性
坑点: Stream 只能被消费一次!
List list = Arrays.asList("a", "b", "c");
Stream stream = list.stream();
// 第一次使用
stream.forEach(System.out::println); // 输出 a b c
// 第二次使用会抛出异常
try {
stream.forEach(System.out::println);
} catch (IllegalStateException e) {
System.out.println("Oops! Stream已经关闭了: " + e.getMessage());
}
解释:
Stream 就像是一个迭代器,一旦遍历结束,它就被"消耗"掉了。如果你尝试再次使用它,就会抛出 IllegalStateException。解决方案是每次需要时都重新创建 Stream。
📌 2. 并行流的线程安全问题
坑点: 并行流并不总是线程安全的!
List numbers = IntStream.range(0, 10000).boxed().collect(Collectors.toList());
List unsafeList = new ArrayList<>();
// 错误的使用方式 - 线程不安全
numbers.parallelStream().forEach(unsafeList::add);
System.out.println("不安全的List大小: " + unsafeList.size()); // 通常不会输出10000
// 正确的使用方式
List safeList = numbers.parallelStream().collect(Collectors.toList());
System.out.println("安全的List大小: " + safeList.size()); // 总是输出10000
解释:
ArrayList 不是线程安全的集合,在并行流中直接操作会导致数据丢失或不一致。正确做法是使用线程安全的收集器(如 Collectors.toList())或使用线程安全的集合(如 Vector)。
📌 3. 流操作的顺序性
坑点: 某些操作会破坏流的顺序!
List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
// 有序流
System.out.println("有序流:");
numbers.stream()
.filter(n -> n % 2 == 0)
<

957

被折叠的 条评论
为什么被折叠?



