Java Stream 流詳解
Stream 是 Java 8 引入的 API,用于高效處理集合數據(如 List
、Set
、Map
等)。它支持函數式編程風格,能實現復雜的查詢、過濾、映射等操作,并支持并行處理以提升性能。
核心特點
- 非存儲數據結構:不存儲數據,僅通過計算管道傳遞數據。
- 不修改源數據:所有操作生成新流,不影響原始集合。
- 惰性求值:中間操作延遲執行,直到遇到終止操作才觸發計算。
- 可消費性:流只能被遍歷一次,終止操作后流即失效。
操作分類
類型 | 操作 | 示例 |
---|---|---|
創建流 | 從集合/數組生成流 | list.stream() , Arrays.stream(array) |
中間操作 | 返回新流(延遲執行) | filter() , map() , sorted() , distinct() |
終止操作 | 觸發計算并返回結果(非流類型) | collect() , forEach() , reduce() , count() |
常用操作詳解
1. 創建流
// 從集合創建
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream1 = list.stream();// 從數組創建
String[] array = {"a", "b", "c"};
Stream<String> stream2 = Arrays.stream(array);// 直接創建
Stream<String> stream3 = Stream.of("a", "b", "c");// 生成無限流(需限制大小)
Stream<Integer> infiniteStream = Stream.iterate(0, n -> n + 1).limit(10); // 0,1,2,...,9
2. 中間操作(鏈式調用)
-
filter(Predicate<T>)
:過濾元素stream.filter(s -> s.startsWith("a")); // 保留以"a"開頭的元素
-
map(Function<T,R>)
:元素轉換stream.map(String::toUpperCase); // 轉為大寫 ["A","B","C"]
-
flatMap(Function<T,Stream<R>>)
:扁平化嵌套流List<List<String>> nestedList = Arrays.asList(Arrays.asList("a", "b"),Arrays.asList("c", "d") ); nestedList.stream().flatMap(List::stream) // 合并為["a","b","c","d"].forEach(System.out::println);
-
distinct()
:去重Stream.of(1, 2, 2, 3).distinct(); // [1, 2, 3]
-
sorted()
:排序Stream.of(3, 1, 2).sorted(); // [1, 2, 3]
-
limit(long n)
:截取前 n 個元素Stream.iterate(0, i -> i + 1).limit(3); // [0, 1, 2]
3. 終止操作
-
collect(Collector)
:轉換為集合List<String> list = stream.collect(Collectors.toList()); // 轉List Set<String> set = stream.collect(Collectors.toSet()); // 轉Set
-
forEach(Consumer<T>)
:遍歷元素stream.forEach(System.out::println); // 打印每個元素
-
reduce()
:聚合計算Optional<Integer> sum = Stream.of(1, 2, 3).reduce((a, b) -> a + b); // 6
-
count()
:統計元素數量long count = stream.filter(s -> !s.isEmpty()).count();
-
匹配檢查
boolean anyMatch = stream.anyMatch(s -> s.contains("a")); // 任一元素匹配 boolean allMatch = stream.allMatch(s -> s.length() > 0); // 所有元素匹配
并行流
通過多線程加速處理大數據集:
// 創建并行流
List<String> result = list.parallelStream().filter(s -> s.length() > 2).collect(Collectors.toList());
注意:并行流需確保操作是線程安全的(如避免修改共享狀態)。
實戰示例
// 示例:從用戶列表中篩選年齡≥18的用戶,按姓名排序,提取前10個
List<User> users = ...; // 數據源List<String> result = users.stream().filter(user -> user.getAge() >= 18) // 過濾.sorted(Comparator.comparing(User::getName)) // 排序.limit(10) // 截取.map(User::getName) // 提取姓名.collect(Collectors.toList()); // 轉為List
注意事項
- 流不可復用:終止操作后流即關閉,再次使用會拋出
IllegalStateException
。 - 避免副作用:操作中不要修改外部變量(使用無狀態函數)。
- 性能考量:小數據集用順序流,大數據集用并行流(需測試驗證)。
Stream API 大幅簡化了集合操作代碼,結合 Lambda 表達式,使 Java 處理數據更簡潔高效。