<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # Java 流 原文:http://zetcode.com/lang/java/streams/ 在 Java 教程的這一部分中,我們將使用流。 流極大地改善了 Java 中數據的處理。 ## Java 流定義 流是來自源的一系列元素,支持順序和并行聚合操作。 常見的聚合操作是:過濾,映射,縮小,查找,匹配和排序。 源可以是將數據提供給流的集合,IO 操作或數組。 Java 集合是一種內存中的數據結構,所有元素都包含在內存中,而流是一種數據結構,其中的所有元素都是按需計算的。 與顯式迭代的集合(外部迭代)相反,流操作為我們在后臺進行迭代。 從 Java8 開始,Java 集合具有`stream()`方法,該方法從集合中返回流。 `Stream`接口在`java.util.stream`包中定義。 對流進行的操作會在不修改其源的情況下產生結果。 ## 流的特征 * 流不存儲數據; 相反,它們從諸如集合,數組或 IO 通道之類的源中提供數據。 * 流不修改數據源。 例如,在執行過濾操作時,它們會將數據轉換為新的流。 * 許多流操作是延遲求值的。 這允許自動代碼優化和短路求值。 * 流可以是無限的。 諸如`limit()`之類的方法使我們可以從無限流中獲得一些結果。 * 在流的生存期內,流的元素只能訪問一次。 像`Iterator`一樣,必須生成新的流以重新訪問源中的相同元素。 * 流具有用于流元素內部迭代的方法,例如`forEach()`和`forEachOrdered()`。 * 流支持類似 SQL 的操作和常用函數式操作,例如過濾,映射,縮小,查找,匹配和排序。 ## Java 流管道 流管道由源,中間操作和終端操作組成。 中間操作返回新的修改后的流; 因此,可以鏈接多個中間操作。 另一方面,終端操作返回`void`或一個值。 終端操作后,將無法再使用該流。 使終端操作短路意味著流可以在處理所有值之前終止。 如果流是無限的,這很有用。 中間操作是懶惰的。 在執行終端操作之前,它們不會被調用。 當我們處理較大的數據流時,這可以提高性能。 ## Java 創建流 流是從各種源創建的,例如集合,數組,字符串,IO 資源或生成器。 `CreatingStreams.java` ```java package com.zetcode; import java.util.Arrays; import java.util.List; import java.util.stream.IntStream; import java.util.stream.Stream; public class CreatingStreams { public static void main(String[] args) { List<String> words = Arrays.asList("pen", "coin", "desk", "chair"); String word = words.stream().findFirst().get(); System.out.println(word); Stream<String> letters = Arrays.stream(new String[]{ "a", "b", "c"}); System.out.printf("There are %d letters%n", letters.count()); String day = "Sunday"; IntStream istr = day.codePoints(); String s = istr.filter(e -> e != 'n').collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString(); System.out.println(s); } } ``` 在此示例中,我們使用從列表,數組和字符串創建的流。 ```java List<String> words = Arrays.asList("pen", "coin", "desk", "chair"); ``` 將創建一個字符串列表。 ```java String word = words.stream().findFirst().get(); ``` 使用`stream`方法,我們從列表集合創建一個流。 在流上,我們調用`findFirst()`方法,該方法返回流的第一個元素。 (它返回一個`Optional`,我們使用`get()`方法從中獲取值。) ```java Stream<String> letters = Arrays.stream(new String[]{ "a", "b", "c"}); System.out.printf("There are %d letters%n", letters.count()); ``` 我們從數組創建流。 流的`count()`方法返回流中的元素數。 ```java String day = "Sunday"; IntStream istr = day.codePoints(); String s = istr.filter(e -> e != 'n').collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString(); System.out.println(s); ``` 在這里,我們從字符串創建流。 我們過濾字符并從過濾的字符構建新的字符串。 ```java $ java com.zetcode.CreatingStreams pen There are 3 letters Suday ``` 這是輸出。 `Stream`有三種數值流:`IntStream`,`DoubleStream`和`LongStream`。 `CreatingStreams2.java` ```java package com.zetcode; import java.util.stream.DoubleStream; import java.util.stream.IntStream; import java.util.stream.LongStream; public class CreatingStreams2 { public static void main(String[] args) { IntStream integers = IntStream.rangeClosed(1, 16); System.out.println(integers.average().getAsDouble()); DoubleStream doubles = DoubleStream.of(2.3, 33.1, 45.3); doubles.forEachOrdered(e -> System.out.println(e)); LongStream longs = LongStream.range(6, 25); System.out.println(longs.count()); } } ``` 該示例適用于上述三個類。 ```java IntStream integers = IntStream.rangeClosed(1, 16); System.out.println(integers.average().getAsDouble()); ``` 使用`IntStream.rangeClosed()`方法創建整數流。 我們將其平均值打印到控制臺。 ```java DoubleStream doubles = DoubleStream.of(2.3, 33.1, 45.3); doubles.forEachOrdered(e -> System.out.println(e)); ``` 使用`DoubleStream.of()`方法創建雙精度值流。 我們使用`forEachOrdered()`方法將元素的有序列表打印到控制臺。 ```java LongStream longs = LongStream.range(6, 25); System.out.println(longs.count()); ``` 用`LongStream.range()`方法創建一個長整數的字符串。 我們使用`count()`方法打印元素的數量。 ```java $ java com.zetcode.CreatingStreams2 8.5 2.3 33.1 45.3 19 ``` 這是示例的輸出。 `Stream.of()`方法返回其元素為指定值的順序有序流。 `CreatingStreams3.java` ```java package com.zetcode; import java.util.Comparator; import java.util.stream.Stream; public class CreatingStreams3 { public static void main(String[] args) { Stream<String> colours = Stream.of("red", "green", "blue"); String col = colours.skip(2).findFirst().get(); System.out.println(col); Stream<Integer> nums = Stream.of(3, 4, 5, 6, 7); int maxVal = nums.max(Comparator.naturalOrder()).get(); System.out.println(maxVal); } } ``` 在示例中,我們使用`Stream.of()`方法創建兩個流。 ```java Stream<String> colours = Stream.of("red", "green", "blue"); ``` 將創建三個字符串流。 ```java String col = colours.skip(2).findFirst().get(); ``` 使用`skip()`方法,我們跳過了兩個元素,而使用`findFirst()`方法只找到了一個元素。 ```java Stream<Integer> nums = Stream.of(3, 4, 5, 6, 7); int maxVal = nums.max(Comparator.naturalOrder()).get(); ``` 我們創建一個整數流并找到其最大數目。輸出如下: ```java $ java com.zetcode.CreatingStreams3 blue 7 ``` 創建流的其他方法是:`Stream.iterate()`和`Stream.generate()`。 `CreatingStreams4.java` ```java package com.zetcode; import java.util.Random; import java.util.stream.Stream; public class CreatingStreams4 { public static void main(String[] args) { Stream<Integer> s1 = Stream.iterate(5, n -> n * 2).limit(10); s1.forEach(System.out::println); Stream.generate(new Random()::nextDouble) .map(e -> (e * 10)) .limit(5) .forEach(System.out::println); } } ``` 在示例中,我們使用`Stream.iterate()`和`Stream.generate()`創建兩個流。 ```java Stream<Integer> s1 = Stream.iterate(5, n -> n * 2).limit(10); s1.forEach(System.out::println); ``` `Stream.iterate()`返回通過將函數迭代應用到初始元素而產生的無限順序有序流。 初始元素稱為種子。 通過將函數應用于第一個元素來生成第二個元素。 通過將函數應用于第二個元素等來生成第三個元素。 ```java Stream.generate(new Random()::nextDouble) .map(e -> (e * 10)) .limit(5) .forEach(System.out::println); ``` 使用`Stream.generate()`方法創建五個隨機雙打的流。 每個元素乘以十。 最后,我們遍歷流并將每個元素打印到控制臺。輸出如下: ```java $ java com.zetcode.CreatingStreams4 5 10 20 40 80 160 320 640 1280 2560 8.704675577530493 5.732011478196306 3.8978402578067515 3.6986033299500933 6.0976417139147205 ``` 可以從文件創建流。 `CreatingStreams5.java` ```java package com.zetcode; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.stream.Stream; public class CreatingStreams5 { public static void main(String[] args) throws IOException { Path path = Paths.get("/home/janbodnar/myfile.txt"); Stream<String> stream = Files.lines(path); stream.forEach(System.out::println); } } ``` 該示例讀取文件并使用流打印其內容。 ```java Path path = Paths.get("/home/janbodnar/myfile.txt"); ``` 使用`Paths.get()`方法創建`Path`對象。 `Path`對象用于在文件系統中定位文件。 ```java Stream<String> stream = Files.lines(path); ``` 從路徑開始,我們使用`Files.lines()`方法創建一個流; 流的每個元素都是文件中的一行。 ```java stream.forEach(System.out::println); ``` 我們瀏覽流中的元素并將它們打印到控制臺。 ## 內部和外部迭代 根據誰控制迭代過程,我們區分外部和內部迭代。 外部迭代,也稱為活動或顯式迭代,由程序員處理。 在 Java8 之前,它是 Java 中唯一的迭代類型。 對于外部迭代,我們使用`for`和`while`循環。 內部迭代(也稱為被動迭代或隱式迭代)由迭代器本身控制。 Java 流中提供了內部迭代。 `ExternalIteration.java` ```java package com.zetcode; import java.util.Arrays; import java.util.Iterator; import java.util.List; public class ExternalIteration { public static void main(String[] args) { List<String> words = Arrays.asList("pen", "coin", "desk", "eye", "bottle"); Iterator it = words.iterator(); while (it.hasNext()) { System.out.println(it.next()); } } } ``` 在代碼示例中,我們從字符串列表中檢索和迭代器對象。 在`while`循環中使用迭代器的`hasNext()`和`next()`方法,我們迭代列表的元素。 在下面的示例中,我們使用外部迭代來迭代相同的列表。 `InternalIteration.java` ```java package com.zetcode; import java.util.Arrays; import java.util.List; public class InternalIteration { public static void main(String[] args) { List<String> words = Arrays.asList("pen", "coin", "desk", "eye", "bottle"); words.stream().forEach(System.out::println); } } ``` 在示例中,我們從列表創建流。 我們使用流的`forEach()`在內部對流元素進行迭代。 ## Java 流過濾器 過濾數據流是流最重要的功能之一。 `filter()`方法是一個中間操作,它返回由與給定謂詞匹配的流元素組成的流。 謂詞是一種返回布爾值的方法。 `FilterStream.java` ```java package com.zetcode; import java.util.Arrays; import java.util.stream.IntStream; public class FilterStream { public static void main(String[] args) { IntStream nums = IntStream.rangeClosed(0, 25); int[] vals = nums.filter(e -> e > 15).toArray(); System.out.println(Arrays.toString(vals)); } } ``` 該代碼示例創建一個整數流。 流被過濾為僅包含大于 15 的值。 ```java IntStream nums = IntStream.rangeClosed(0, 25); ``` 使用`IntStream`,創建了 26 個整數的流。 `rangeClose()`方法從兩個值的邊界創建整數流; 這兩個值(開始和結束)都包含在范圍內。 ```java int[] vals = nums.filter(e -> e > 15).toArray(); ``` 我們將 lambda 表達式(`e -> e > 15`)傳遞給`filter()`函數; 對于大于 15 的值,該表達式返回`true`。`toArray()`是將流轉換為整數數組的終端操作。 ```java System.out.println(Arrays.toString(vals)); ``` 將數組打印到控制臺。 ```java $ java com.zetcode.FilterStream [16, 17, 18, 19, 20, 21, 22, 23, 24, 25] ``` 該示例產生此輸出。 下一個示例生成事件編號列表。 `FilterStream2.java` ```java package com.zetcode; import java.util.stream.IntStream; public class FilterStream2 { public static void main(String[] args) { IntStream nums = IntStream.rangeClosed(0, 30); nums.filter(FilterStream2::isEven).forEach(System.out::println); } private static boolean isEven(int e) { return e % 2 == 0; } } ``` 為了從流中獲得偶數,我們將`isEven()`方法引用傳遞給`filter()`方法。 ```java nums.filter(FilterStream2::isEven).forEach(System.out::println); ``` 雙冒號 `::` 運算符用于傳遞方法引用。 `forEach()`方法是對流的元素進行迭代的終端操作。 它引用了`System.out.println()`方法的方法。 ## 跳過和限制元素 `skip(n)`方法跳過流的前`n`個元素,`limit(m)`方法將流中的元素數限制為`m`。 `SkipLimit.java` ```java package com.zetcode; import java.util.stream.IntStream; public class SkipLimit { public static void main(String[] args) { IntStream s = IntStream.range(0, 15); s.skip(3).limit(5).forEach(System.out::println); } } ``` 該示例創建了一個十五個整數的流。 我們使用`skip()`方法跳過前三個元素,并將元素個數限制為 5。輸出如下: ```java $ java com.zetcode.SkipLimit 3 4 5 6 7 ``` ## Java 流排序元素 `sorted()`方法根據提供的`Comparator`對該流的元素進行排序。 `Sorting.java` ```java package com.zetcode; import java.util.Comparator; import java.util.stream.IntStream; public class Sorting { public static void main(String[] args) { IntStream nums = IntStream.of(4, 3, 2, 1, 8, 6, 7, 5); nums.boxed().sorted(Comparator.reverseOrder()) .forEach(System.out::println); } } ``` 該示例按降序對整數元素進行排序。 `boxed()`方法將`IntStream`轉換為`Stream<Integer>`。輸出如下: ```java $ java com.zetcode.Sorting 8 7 6 5 4 3 2 1 ``` 下一個示例顯示如何比較對象流。 `Sorting2.java` ```java package com.zetcode; import java.util.Arrays; import java.util.Comparator; import java.util.List; class Car { private String name; private int price; public Car(String name, int price ) { this.name = name; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } @Override public String toString() { return "Car{" + "name=" + name + ", price=" + price + '}'; } } public class Sorting2 { public static void main(String[] args) { List<Car> cars = Arrays.asList(new Car("Citroen", 23000), new Car("Porsche", 65000), new Car("Skoda", 18000), new Car("Volkswagen", 33000), new Car("Volvo", 47000)); cars.stream().sorted(Comparator.comparing(Car::getPrice)) .forEach(System.out::println); } } ``` 該示例按價格對汽車進行排序。 ```java List<Car> cars = Arrays.asList(new Car("Citroen", 23000), new Car("Porsche", 65000), new Car("Skoda", 18000), new Car("Volkswagen", 33000), new Car("Volvo", 47000)); ``` 將創建汽車列表。 ```java cars.stream().sorted(Comparator.comparing(Car::getPrice)) .forEach(System.out::println); ``` 使用`stream()`方法從列表中生成流。 我們傳遞了`Car`的`getPrice()`方法的引用,該方法在按汽車價格進行比較時使用。輸出如下: ```java $ java com.zetcode.Sorting2 Car{name=Skoda, price=18000} Car{name=Citroen, price=23000} Car{name=Volkswagen, price=33000} Car{name=Volvo, price=47000} Car{name=Porsche, price=65000} ``` ## Java 流唯一值 `distinct()`方法返回由唯一元素組成的流。 `UniqueElements.java` ```java package com.zetcode; import java.util.Arrays; import java.util.stream.IntStream; public class UniqueElements { public static void main(String[] args) { IntStream nums = IntStream.of(1, 1, 3, 4, 4, 6, 7, 7); int a[] = nums.distinct().toArray(); System.out.println(Arrays.toString(a)); } } ``` 該示例從整數流中刪除重復的值。 ```java IntStream nums = IntStream.of(1, 1, 3, 4, 4, 6, 7, 7); ``` 流中有三個重復的值。 ```java int a[] = nums.distinct().toArray(); ``` 我們使用`distinct()`方法刪除重復項。輸出如下: ```java $ java com.zetcode.UniqueElements [1, 3, 4, 6, 7] ``` ## Java 流映射 可以將元素更改為新的流; 原始來源未修改。 `map()`方法返回一個流,該流由將給定函數應用于流的元素的結果組成。 `map()`是一個中間操作。 `Mapping.java` ```java package com.zetcode; import java.util.Arrays; import java.util.stream.IntStream; public class Mapping { public static void main(String[] args) { IntStream nums = IntStream.of(1, 2, 3, 4, 5, 6, 7, 8); int[] squares = nums.map(e -> e * e).toArray(); System.out.println(Arrays.toString(squares)); } } ``` 我們在流的每個元素上映射一個轉換函數。 ```java int[] squares = nums.map(e -> e * e).toArray(); ``` 我們在流上應用一個 lambda 表達式(`e -> e * e`):每個元素都是平方的。 創建一個新的流,并使用`toArray()`方法將其轉換為數組。輸出如下: ```java $ java com.zetcode.Mapping [1, 4, 9, 16, 25, 36, 49, 64] ``` 在下一個示例中,我們轉換字符串流。 `Mapping2.java` ```java package com.zetcode; import java.util.stream.Stream; public class Mapping2 { public static void main(String[] args) { Stream<String> words = Stream.of("cardinal", "pen", "coin", "globe"); words.map(Mapping2::capitalize).forEach(System.out::println); } private static String capitalize(String word) { word = word.substring(0, 1).toUpperCase() + word.substring(1).toLowerCase(); return word; } } ``` 我們有一串串的字符串。 我們將流中的每個字符串都大寫。 ```java words.map(Mapping2::capitalize).forEach(System.out::println); ``` 我們將對`capitalize()`方法的引用傳遞給`map()`方法。輸出如下: ```java $ java com.zetcode.Mapping2 Cardinal Pen Coin Globe ``` ## Java 流歸約 歸約是將流聚合為類或原始類型的終端操作。 `Reduction.java` ```java package com.zetcode; import java.util.stream.IntStream; public class Reduction { public static void main(String[] args) { IntStream nums = IntStream.of(1, 2, 3, 4, 5, 6, 7, 8); int maxValue = nums.max().getAsInt(); System.out.printf("The maximum value is: %d%n", maxValue); } } ``` 從整數流中獲取最大值是一種歸約運算。 ```java int maxValue = nums.max().getAsInt(); ``` 使用`max()`方法,我們獲得了流的最大元素。 該方法返回一個`Optional`,使用`getAsInt()`方法從中獲得整數。輸出如下: ```java $ java com.zetcode.Reduction The maximum value is: 8 ``` 可以使用`reduce()`方法創建自定義歸約。 `Reduction2.java` ```java package com.zetcode; import java.util.stream.IntStream; public class Reduction2 { public static void main(String[] args) { IntStream nums = IntStream.of(1, 2, 3, 4, 5, 6, 7, 8); int product = nums.reduce((a, b) -> a * b).getAsInt(); System.out.printf("The product is: %d%n", product); } } ``` 該示例返回流中整數元素的乘積。輸出如下: ```java $ java com.zetcode.Reduction The product is: 40320 ``` ## Java 流收集操作 收集是一種終端歸約操作,可將流的元素還原為 Java 集合,字符串,值或特定的分組。 `Collecting.java` ```java package com.zetcode; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; class Car { private String name; private int price; public Car(String name, int price) { this.name = name; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } @Override public String toString() { return "Car{" + "name=" + name + ", price=" + price + '}'; } } public class Collecting { public static void main(String[] args) { List<Car> cars = Arrays.asList(new Car("Citroen", 23000), new Car("Porsche", 65000), new Car("Skoda", 18000), new Car("Volkswagen", 33000), new Car("Volvo", 47000)); List<String> names = cars.stream().map(Car::getName) .filter(name -> name.startsWith("Vo")) .collect(Collectors.toList()); for (String name: names) { System.out.println(name); } } } ``` 該示例從汽車對象列表創建流,按汽車名稱過濾汽車,并返回匹配的汽車名稱列表。 ```java List<String> names = cars.stream().map(Car::getName) .filter(name -> name.startsWith("Vo")) .collect(Collectors.toList()); ``` 在管道的最后,我們使用`collect()`方法進行轉換。 輸出如下: ```java $ java com.zetcode.Collecting Volkswagen Volvo ``` 在下一個示例中,我們使用`collect()`方法對數據進行分組。 `Collecting2.java` ```java package com.zetcode; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; public class Collecting2 { public static void main(String[] args) { List<String> items = Arrays.asList("pen", "book", "pen", "coin", "book", "desk", "book", "pen", "book", "coin"); Map<String, Long> result = items.stream().collect( Collectors.groupingBy( Function.identity(), Collectors.counting() )); for (Map.Entry<String, Long> entry : result.entrySet()) { String key = entry.getKey(); Long value = entry.getValue(); System.out.format("%s: %d%n", key, value); } } } ``` 該代碼示例按元素在流中的出現將其分組。 ```java Map<String, Long> result = items.stream().collect( Collectors.groupingBy( Function.identity(), Collectors.counting() )); ``` 使用`Collectors.groupingBy()`方法,我們可以計算流中元素的出現次數。 該操作返回一個映射。 ```java for (Map.Entry<String, Long> entry : result.entrySet()) { String key = entry.getKey(); Long value = entry.getValue(); System.out.format("%s: %d%n", key, value); } ``` 我們瀏覽映射并打印其鍵/值對。輸出如下: ```java $ java com.zetcode.Collecting2 desk: 1 book: 4 pen: 3 coin: 2 ``` Java 教程的這一部分介紹了流。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看