java中的stream代表什么 流式編程stream的5個核心操作

Java中stream的5個核心操作是過濾、映射、排序、規約、收集。1. 過濾(Filter)用于篩選符合條件的元素;2. 映射(map)將元素轉換為另一種形式;3. 排序(sorted)對元素進行自然或自定義排序;4. 規約(reduce)將元素聚合成一個結果;5. 收集(collect)將結果存儲到集合等數據結構中。

java中的stream代表什么 流式編程stream的5個核心操作

Java中的Stream,簡單來說,它不是一種數據結構,而是一種處理數據的方式。你可以把它想象成工廠里的流水線,數據(比如一個List)就像原材料,經過流水線上的一系列操作(過濾、轉換、收集等等),最終變成你想要的產品。流式編程的核心就是圍繞這條“流水線”展開,讓數據處理更加簡潔、高效。

java中的stream代表什么 流式編程stream的5個核心操作

流式編程Stream的5個核心操作

java中的stream代表什么 流式編程stream的5個核心操作

什么是Stream,它和集合有什么區別?

Stream和集合(Collection)經常被放在一起比較,但它們本質上是不同的。集合是用來存儲數據的,而Stream是用來處理數據的。集合關注的是數據的存儲和組織,而Stream關注的是對數據的計算和轉換。一個集合可以創建多個Stream,每個Stream都可以對集合中的數據進行不同的處理。

立即學習Java免費學習筆記(深入)”;

舉個例子,你有一個List names,你可以用它創建一個Stream,然后過濾掉長度小于5的字符串,再把剩下的字符串轉換成大寫,最后收集到一個新的List中。這個過程中,原始的names集合并沒有改變,Stream只是提供了一種處理數據的方式。

java中的stream代表什么 流式編程stream的5個核心操作

Stream操作可以分為兩種:中間操作(Intermediate Operations)和終端操作(Terminal Operations)。中間操作返回一個新的Stream,可以鏈式調用,而終端操作返回一個結果或者產生副作用,標志著Stream操作的結束。

Stream的5個核心操作具體指的是哪些?

  1. 過濾 (Filtering):filter() 方法允許你根據指定的條件篩選出符合條件的元素。例如,你可以過濾掉集合中的空字符串或者負數。

    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, -1, -2); List<Integer> positiveNumbers = numbers.stream()                                      .filter(n -> n > 0)                                      .collect(Collectors.toList()); // positiveNumbers: [1, 2, 3, 4, 5]
  2. 映射 (Mapping):map() 方法可以將Stream中的每個元素轉換成另一種類型。例如,你可以將字符串列表轉換成對應的長度列表。

    List<String> words = Arrays.asList("java", "stream", "api"); List<Integer> wordLengths = words.stream()                                  .map(String::length)                                  .collect(Collectors.toList()); // wordLengths: [4, 6, 3]
  3. 排序 (Sorting):sorted() 方法可以對Stream中的元素進行排序。你可以使用自然排序,也可以自定義排序規則。

    List<String> names = Arrays.asList("Charlie", "Alice", "Bob"); List<String> sortedNames = names.stream()                                 .sorted() // 自然排序                                 .collect(Collectors.toList()); // sortedNames: [Alice, Bob, Charlie]  List<String> sortedNamesByLength = names.stream()                                        .sorted(Comparator.comparingInt(String::length)) // 按長度排序                                        .collect(Collectors.toList()); // sortedNamesByLength: [Bob, Alice, Charlie]
  4. 規約 (reduction):reduce() 方法可以將Stream中的元素聚合成一個結果。例如,你可以計算列表中所有元素的總和。

    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); Optional<Integer> sum = numbers.stream()                                .reduce(Integer::sum); // 求和 // sum: Optional[15]  int product = numbers.stream()                      .reduce(1, (a, b) -> a * b); // 求積,初始值為1 // product: 120
  5. 收集 (Collecting):collect() 方法可以將Stream中的元素收集到不同的數據結構中,比如List、Set、Map等。

    List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Alice"); List<String> distinctNames = names.stream()                                   .distinct() // 去重                                   .collect(Collectors.toList()); // distinctNames: [Alice, Bob, Charlie]  Map<String, Integer> nameLengths = names.stream()                                         .collect(Collectors.toMap(name -> name, String::length, (oldValue, newValue) -> oldValue)); // 轉換成Map // nameLengths: {Alice=5, Bob=3, Charlie=7}

如何避免Stream操作中的常見錯誤?

在使用Stream時,有一些常見的錯誤需要避免。

  • 多次使用同一個Stream:Stream只能被消費一次。一旦終端操作被調用,Stream就關閉了。如果需要再次使用相同的數據,需要重新創建一個Stream。

    Stream<String> stream = Arrays.asList("a", "b", "c").stream(); stream.forEach(System.out::println); // OK // stream.forEach(System.out::println); // 拋出異常:java.lang.IllegalStateException: stream has already been operated upon or closed
  • 忘記終端操作:如果沒有終端操作,Stream操作鏈不會執行。

    Arrays.asList("a", "b", "c").stream().filter(s -> s.startsWith("a")); // 什么都不會發生
  • 使用并行Stream時的數據競爭:并行Stream可以提高處理速度,但也可能導致數據競爭問題。要確保傳遞給并行Stream的操作是線程安全的。

    List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5)); numbers.parallelStream().forEach(n -> {     // 錯誤示例:修改共享狀態,可能導致數據競爭     // numbers.set(n - 1, n * 2); });

除了這5個核心操作,Stream還有哪些常用的操作?

除了上面提到的5個核心操作,Stream API還提供了很多其他有用的操作。

  • peek():peek() 方法允許你在Stream的每個元素被處理之前執行一些操作,比如打印日志或者修改元素的狀態。它主要用于調試和觀察Stream的處理過程。

    List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); List<String> modifiedNames = names.stream()                                   .peek(name -> System.out.println("Processing: " + name))                                   .map(String::toUpperCase)                                   .collect(Collectors.toList()); // 輸出: // Processing: Alice // Processing: Bob // Processing: Charlie // modifiedNames: [ALICE, BOB, CHARLIE]
  • flatMap():flatMap() 方法可以將Stream中的每個元素轉換成一個Stream,然后將所有的Stream合并成一個Stream。它常用于處理嵌套集合。

    List<List<String>> nestedList = Arrays.asList(         Arrays.asList("a", "b"),         Arrays.asList("c", "d"),         Arrays.asList("e", "f") ); List<String> flattenedList = nestedList.stream()                                        .flatMap(Collection::stream)                                        .collect(Collectors.toList()); // flattenedList: [a, b, c, d, e, f]
  • findFirst() 和 findAny():findFirst() 方法返回Stream中的第一個元素,而 findAny() 方法返回Stream中的任意一個元素。它們通常與 filter() 方法一起使用。

    List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); Optional<String> firstEvenLengthName = names.stream()                                              .filter(name -> name.length() % 2 == 0)                                              .findFirst(); // 找到第一個長度為偶數的字符串 // firstEvenLengthName: Optional[Alice]  Optional<String> anyEvenLengthName = names.parallelStream()                                           .filter(name -> name.length() % 2 == 0)                                           .findAny(); // 找到任意一個長度為偶數的字符串 (并行流,結果不確定) // anyEvenLengthName: Optional[Alice] (也可能是 Bob 或 Charlie,取決于并行執行的順序)

Stream在實際項目中有哪些應用場景?

Stream API在實際項目中有廣泛的應用場景。

  • 數據清洗和轉換:從數據庫或者文件中讀取數據后,可以使用Stream API對數據進行清洗和轉換,比如去除空格、轉換數據類型、過濾無效數據等。
  • 報表生成:可以利用Stream API對數據進行分組、聚合、排序,然后生成各種報表。
  • 數據分析:Stream API可以用于實現各種數據分析算法,比如計算平均值、最大值、最小值、標準差等。
  • 并行計算:可以使用并行Stream來加速數據處理過程,特別是在處理大數據量時。

總之,Stream API提供了一種簡潔、高效的方式來處理數據,可以大大提高開發效率和代碼質量。理解和掌握Stream API是Java開發者的必備技能。

? 版權聲明
THE END
喜歡就支持一下吧
點贊12 分享