Stream
是 Java 8 引入的一個強大的功能,用于處理集合(Collection)或數組中的數據。它提供了一種聲明式的編程方式,可以極大地簡化對數據的操作,例如過濾、排序、映射和聚合等。
1. 什么是 Stream 流?
- 定義:
Stream
是一個來自數據源(如集合、數組等)的元素序列,支持順序和并行操作。 - 特點:
- 惰性求值(Lazy Evaluation):Stream 的中間操作不會立即執行,只有在終端操作觸發時才會真正執行。
- 不可變性:Stream 操作不會修改原始數據源,而是生成新的流或結果。
- 鏈式調用:多個操作可以通過鏈式調用的方式組合在一起。
2. Stream 的工作流程
使用 Stream 流通常分為以下三個步驟:
- 創建流:從數據源(如集合、數組)創建一個 Stream。
- 中間操作:對流中的數據進行一系列操作(如過濾、映射、排序等),返回一個新的流。
- 終端操作:觸發流的執行,并生成最終結果(如收集到集合、計算總數等)。
3. 創建 Stream
可以通過多種方式創建 Stream:
(1)從集合創建
List<String> list = Arrays.asList("A", "B", "C"); Stream<String> stream = list.stream(); // 創建串行流 Stream<String> parallelStream = list.parallelStream(); // 創建并行流
(2)從數組創建
String[] array = {"A", "B", "C"}; Stream<String> stream = Arrays.stream(array);
(3)使用靜態方法
// 創建一個包含指定元素的流 Stream<String> stream = Stream.of("A", "B", "C");// 創建一個空流 Stream<String> emptyStream = Stream.empty();
4. 中間操作
中間操作是對流中的數據進行處理,返回一個新的流。常見的中間操作包括:
(1)過濾(filter
)
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);// 過濾出偶數 Stream<Integer> filteredStream = numbers.stream().filter(n -> n % 2 == 0);
(2)映射(map
)
List<String> words = Arrays.asList("apple", "banana", "cherry");// 將每個單詞轉換為大寫 Stream<String> upperCaseStream = words.stream().map(String::toUpperCase);
(3)排序(sorted
)
List<Integer> numbers = Arrays.asList(5, 3, 8, 1);// 升序排序 Stream<Integer> sortedStream = numbers.stream().sorted();// 自定義排序規則 Stream<Integer> customSortedStream = numbers.stream().sorted(Comparator.reverseOrder());
(4)去重(distinct
)
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4);// 去重后的流 Stream<Integer> distinctStream = numbers.stream().distinct();
(5)限制和跳過(limit
和 skip
)
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);// 取前 3 個元素 Stream<Integer> limitedStream = numbers.stream().limit(3);// 跳過前 2 個元素 Stream<Integer> skippedStream = numbers.stream().skip(2);
5. 終端操作
終端操作會觸發流的執行,并生成最終結果。常見的終端操作包括:
(1)收集結果(collect
)
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);// 收集為 List List<Integer> result = numbers.stream().filter(n -> n % 2 == 0).collect(Collectors.toList());// 收集為 Set Set<Integer> resultSet = numbers.stream().filter(n -> n % 2 == 0).collect(Collectors.toSet());
(2)統計信息(count
、min
、max
等)
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);// 統計元素個數 long count = numbers.stream().count();// 查找最大值 Optional<Integer> max = numbers.stream().max(Integer::compareTo);// 查找最小值 Optional<Integer> min = numbers.stream().min(Integer::compareTo);
(3)遍歷(forEach
)
List<String> words = Arrays.asList("apple", "banana", "cherry");// 打印每個單詞 words.stream().forEach(System.out::println);
(4)判斷條件(anyMatch
、allMatch
、noneMatch
)
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);// 是否存在偶數 boolean hasEven = numbers.stream().anyMatch(n -> n % 2 == 0);// 是否所有元素都是偶數 boolean allEven = numbers.stream().allMatch(n -> n % 2 == 0);// 是否沒有偶數 boolean noEven = numbers.stream().noneMatch(n -> n % 2 == 0);
6. 并行流
Java 8 提供了并行流(Parallel Stream),可以利用多核 CPU 并行處理數據:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);// 使用并行流計算總和 int sum = numbers.parallelStream().mapToInt(Integer::intValue).sum();
- 優點:對于大數據量的操作,可以顯著提高性能。
- 缺點:并行流可能會引入線程安全問題,且不一定總是比串行流快。
7. Stream 的注意事項
- 一次性消費:Stream 流只能被消費一次,再次使用需要重新創建。
- 避免副作用:盡量避免在 Stream 操作中修改外部狀態,保持函數式編程的純函數特性。
- 性能優化:合理選擇中間操作和終端操作,避免不必要的復雜操作。
8. 總結
Stream 是 Java 8 中非常重要的特性,能夠極大地簡化集合操作。它的主要優勢包括:
- 簡潔性:通過鏈式調用實現復雜的操作邏輯。
- 可讀性:代碼更加直觀,易于理解。
- 高效性:支持并行流,充分利用多核 CPU 性能。
如果你需要處理集合或數組中的數據,推薦優先考慮使用 Stream 流來實現