<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>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] # 簡介 jdk8出來的 ![](https://img.kancloud.cn/d7/ef/d7eff1c312ba8fc52b5171fbbd66742b_1129x565.png) 顯示了過濾,映射,跳過,計數等多步操作,這是一種集合元素的處理方案,而方案是一種函數模型. 圖中每一種方框都是流,調用指定方法,可以從一個流轉換到另一個流. 這里的filter,map,skip都是對函數模型進行操作,集合元素并沒有真正的處理,只有當終結方法count執行的時候,整個模型才會按照指定策略執行操作.這得益于lambda的延遲執行特性. 備注: stream流,其實是一個集合元素的函數模型,它并不是集合,也不是數據結構,其本身并不存儲任何元素(或其他地址值) Stream(流)是一個來自數據源的元素隊列 * 元素是特定類型的對象,形成一個隊列.java中的stream并不會存儲元素,而是按需計算. * **數據源** 流的來源.可以是集合,數組等 和collection不同,stream操作還有兩個基礎特性 * **pipelining**: 中間操作都會返回流對象本身.這樣多個操作可以串聯成一個管道,如同流式風格.這樣做可以對操作進行優化,比如延遲支持和短路 * **內部迭代**: 以前對集合遍歷都是通過Iterator或者增強for的方式,顯示的在集合外部進行迭代,這叫做外部迭代.stream提供了內部迭代的方式,流可以直接調用遍歷方法. # 獲取流 `java.util.stream.Stream<T>`是java8新加入的最常用的流接口(這不是一個函數式接口) 獲取一個流非常簡單,有以下幾種方式 * 所有的collection集合都可以通過stream默認方法獲取流 * stream接口的靜態方法of可以獲取數組對應的流 ## 根據collection獲取流 首先,`java.util.Collection`接口中加入了default方法stream用來獲取流,所以其所有實現類均可獲取流 ~~~ default Stream<E> stream() { return StreamSupport.stream(spliterator(), false); } ~~~ ## strem.parallel()或者parallelStream并行流 創建流時,除非另有說明,否則它始終是串行流。要創建并行流,請調用操作`Collection.parallelStream`或者,調用操作`BaseStream.parallel` ~~~ //切換為順序流 sequential() ~~~ 單個個線程計算`1+2+3+...+1000=?`,java 8代碼為: ~~~ public class DemoTest { public static void main(String[] args) { IntStream strem = IntStream.rangeClosed(1, 1000); int sum = strem.sum(); System.out.println(sum); } } ~~~ 引入并行計算,只需要添加`strem.parallel()`即可,具體如下: ~~~ public class DemoTest { public static void main(String[] args) { IntStream strem = IntStream.rangeClosed(1, 1000); int sum = strem.parallel().sum(); System.out.println(sum); } } ~~~ `java.util.Collection<E>`新添加了兩個默認方法 * default Stream stream() : 返回串行流 * default Stream parallelStream() : 返回并行流 可以發現,stream()和parallelStream()方法返回的都是`java.util.stream.Stream<E>`類型的對象,說明它們在功能的使用上是沒差別的。唯一的差別就是單線程和多線程的執行 ### 并行流的問題 發現一個查詢返回一會是3,一會是4 ~~~ for (int i = 0; i < 100; i++) { List<String> list1 = new ArrayList<>(); List<String> list2 = new ArrayList<>(); list1.add("a"); list1.add("b"); list1.add("c"); list1.add("d"); list1.parallelStream().forEach(list -> list2.add(list)); System.out.println(list2.size()); } ~~~ 循環100次,會出現3,分析原因:ArrayList是線程不安全的,在并行流時,會出現并發問題。所以項目中不要動不動就用ArrayList,在高并發的情況下可能會有問題 **Arraylist本身底層是一個數組,多線程并發下線程并不安全,操作出現的原因無非就是多個線程賦值可能同時操作同一個地址,后賦值的把先賦值的給覆蓋掉了,才會出現這種問題** ## 靜態方法of獲取 參數是一個可變參數,那么我們可以傳遞一個數組 ~~~ public static<T> Stream<T> of(T t) { return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false); } ~~~ ~~~ //集合轉為stream流 ArrayList<Object> list = new ArrayList<>(); Stream<Object> stream1 = list.stream(); HashSet<Object> set = new HashSet<>(); Stream<Object> stream2 = set.stream(); HashMap<Object, Object> map = new HashMap<>(); //獲取鍵存到一個collection集合中 Set<Object> keySet = map.keySet(); Stream<Object> stream3 = keySet.stream(); //獲取值存到coollection中 Collection<Object> values = map.values(); Stream<Object> stream4 = values.stream(); //獲取鍵值對 Set<Map.Entry<Object, Object>> entries = map.entrySet(); Stream<Map.Entry<Object, Object>> stream5 = entries.stream(); //把數組轉換為stream流 Stream<Integer> stream6 = Stream.of(1, 2, 3, 4, 5); //可變參數可以傳遞數組 Integer[] arr = {1, 2, 3, 4, 5, 6}; Stream<Integer> stream7 = Stream.of(arr); ~~~ ## 創建null的流 ~~~ Stream<Object> stream = Stream.ofNullable(null); stream.forEach(System.out::println); ~~~ ## 生成無限流 ~~~ 迭代 // public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) Stream<Integer> stream = Stream.iterate(0, x -> x + 2); stream.limit(10).forEach(System.out::println); // 生成 // public static<T> Stream<T> generate(Supplier<T> s) Stream<Double> stream1 = Stream.generate(Math::random); stream1.limit(10).forEach(System.out::println); ~~~ ## 組合concat ~~~ public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) ~~~ 兩個流合并為一個流,與`java.lang.String`中的concat方法不同 # 常用方法 ![](https://img.kancloud.cn/b3/2a/b32a79a25e8b89c5544e6f43344aa7f0_988x224.png) 這些方法分為兩種: * 延遲方法: 返回值類型仍然是Stream接口自身類型的方法,因此支持鏈式調用 * 終結方法: 返回值類型不再是Stream接口自身類型的方法,因此不再支持類似StringBuilder那樣的鏈式調用,終結方法包括: count和forEach方法 ## 終止方法 ### 逐一處理forEach stream流中的常用方法forEach ~~~ void forEach(Consumer<? super T> action); ~~~ Consumer接口是一個消費型函數式接口 forEach是用來遍歷流中的數據 是一個終結方法,遍歷之后就不能繼續調用Stream流中的其他方法 ### 按照順序取數據forEachOrdered ~~~ List<String> strs = Arrays.asList("a", "b", "c"); strs.stream().forEachOrdered(System.out::print);//abc System.out.println(); strs.stream().forEach(System.out::print);//abc System.out.println(); strs.parallelStream().forEachOrdered(System.out::print);//abc System.out.println(); strs.parallelStream().forEach(System.out::print);//bca ~~~ 先看第一段輸出和第二段輸出,使用的是stream的流,這個是一個串行流,也就是程序是串行執行的,所有看到遍歷的結果都是按照集合的元素放入的順序; 看第三段和第四段輸出,使用的parallelStream的流,這個流表示一個并行流,也就是在程序內部迭代的時候,會幫你免費的并行處理,關于java8的并行處理,會在后期為大家介紹; 第三段代碼的forEachOrdered表示嚴格按照順序取數據,forEach在并行中,隨機排列了;這個也可以看出來,在并行的程序中,如果對處理之后的數據,沒有順序的要求,使用forEach的效率,肯定是要更好的 ### 統計個數count ~~~ long count(); ~~~ 返回是long值不像之前的int值 ### 至少匹配一個元素anyMatch anyMatch方法可以回答“流中是否有一個元素能匹配給定的詞” ~~~ List<String> words = Arrays.asList("Java 8", "Lambdas", "In", "Action"); boolean in = words.stream().anyMatch((x) -> x.equals("In")); System.out.println(in); ~~~ ### 是否匹配所有元素allMatch allMatch方法的工作原理和anyMatch類似,但它會看看流中的元素是否都能匹配給定的 ~~~ boolean isHealthy = menu.stream().allMatch(d -> d.getCalories() < 1000); ~~~ ### 沒有任何元素與給定的匹配noneMatch ~~~ boolean isHealthy = menu.stream().noneMatch(d -> d.getCalories() >= 1000); ~~~ ### 查找元素findAny findAny方法將返回當前流中的任意元素。它可以與其他流操作結合使用。比如,你可能想 找到一道素食菜肴。你可以結合使用filter和findAny方法來實現這個查詢: ~~~ Optional<Dish> dish = menu.stream().filter(Dish::isVegetarian) .findAny(); ~~~ ![](https://img.kancloud.cn/e4/f7/e4f7d83d3701122a60232454c8b144f5_663x90.png) findFirst是查找第一個 ### max,min ~~~ max(Comparator c) ~~~ 求 Stream 中的最大值、最小值。 例:取出 Stream 中最長的字符串 ~~~ String[] testStrings = { "java", "react", "angular", "javascript", "vue" }; Optional<String> max = Stream.of(testStrings).max((p1, p2) -> Integer.compare(p1.length(), p2.length())); System.out.println(max); ~~~ ### 收集collect ~~~ //將流轉換為其他形式 collect(Collector c) ~~~ collect(toList()) 終止操作 由Stream中的值生成一個List列表,也可用collect(toSet())生成一個Set集合 ![](https://img.kancloud.cn/49/2f/492f2e2bedf0baa606c5142e4dbf6002_956x613.png) ~~~ String[] testStrings = { "java", "react", "angular", "vue" }; List<String> list = Stream.of(testStrings).collect(Collectors.toList()); for (int i = 0, length = list.size(); i < length; i++) { System.out.println(list.get(i)); } ~~~ ### 歸約reduce ~~~ //可以將流中元素反復結合起來,得到一個值。返回 T reduce(T iden, BinaryOperator b) //可以將流中元素反復結合起來,得到一個值。返回 Optional<T> reduce(BinaryOperator b) ~~~ ## 中間操作 ### 去重distinct ~~~ @Test public void distinctStream() { Stream<String> distinctStream = Stream.of("bj","shanghai","tianjin","bj","shanghai").distinct(); Stream<String> sortedStream = distinctStream.sorted(Comparator.comparing(String::length)); sortedStream.forEach(x -> System.out.print(x + " ")); } ~~~ 輸出 ~~~ bj tianjin shanghai ~~~ ### 排序sorted ~~~ Stream<Integer> sortedStream = Stream.of(1,3,7,4,5,8,6,2).sorted(); sortedStream.collect(Collectors.toList()).forEach(x -> System.out.print(x + " ")); System.out.println(); Stream<Integer> sortedReverseStream = Stream.of(1,3,7,4,5,8,6,2).sorted(new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o1 - o2; } }); Stream<Integer> sortedReverseStreamV2 = Stream.of(1,3,7,4,5,8,6,2).sorted((Integer o1, Integer o2) -> o2 - o1); sortedReverseStreamV2.collect(Collectors.toList()).forEach(x -> System.out.print(x + " ")); ~~~ 輸出 ~~~ 1 2 3 4 5 6 7 8 8 7 6 5 4 3 2 1 ~~~ ### 過濾filter ~~~ Stream<T> filter(Predicate<? super T> predicate); ~~~ 把一個流轉換為他的子集 ### 映射Map 把流中的元素映射到另一個 ~~~ <R> Stream<R> map(Function<? super T, ? extends R> mapper); ~~~ ### 扁平化flatmap flatmap可用 Stream 替換值,并將多個 Stream 流合并成一個 Stream 流 我們先來看個為什么要使用這個 ~~~ List<String> words = Arrays.asList("Java 8", "Lambdas", "In", "Action"); List<String[]> list = words.stream() .map(word -> word.split("")).distinct().collect(toList()); ~~~ 這個方法的問題在于,傳遞給map方法的Lambda為每個單詞返回了一個String\[\](String 列表)。因此,map返回的流實際上是Stream類型的。你真正想要的是用 Stream來表示一個字符流 ![](https://img.kancloud.cn/b0/fd/b0fdd1e540caeb1ccb363cebaced81ea_679x403.png) 嘗試使用map和Arrays.stream() 首先,你需要一個字符流,而不是數組流。有一個叫作Arrays.stream()的方法可以接受 一個數組并產生一個流,例如: ~~~ String[] arrayOfWords = {"Goodbye", "World"}; Stream<String> streamOfwords = Arrays.stream(arrayOfWords); ~~~ 把它用在前面的那個流水線里,看看會發生什么: ![](https://img.kancloud.cn/c0/3b/c03bd7930f1c230b4637deae9c71a18c_481x120.png) 當前的解決方案仍然搞不定!這是因為,你現在得到的是一個流的列表(更準確地說是 Stream)!的確,你先是把每個單詞轉換成一個字母數組,然后把每個數組變成了一 個獨立的流。 你可以像下面這樣使用flatMap來解決這個問題 ~~~ List<String> words = Arrays.asList("Java 8", "Lambdas", "In", "Action"); List<String> collect = words.stream() .map(word -> word.split("")) .flatMap(Arrays::stream) .distinct() .collect(toList()); ~~~ 使用flatMap方法的效果是,各個數組并不是分別映射成一個流,而是映射成流的內容。所 有使用`map(Arrays::stream)`時生成的單個流都被合并起來,即扁平化為一個流 ![](https://img.kancloud.cn/91/04/91047bc77f6b4965fd42d96eeef62d90_665x489.png) 一言以蔽之,flatmap方法讓你把一個流中的每個值都換成另一個流,然后把所有的流連接 起來成為一個流。 ![](https://img.kancloud.cn/6f/a1/6fa157a47291bd0c90a6d29446e618bf_1082x737.png) ### 取前幾個limit ~~~ Stream<T> limit(long maxSize); ~~~ 參數是long,如果集合當前長度大于參數進行截取,否則不進行截取 ### 跳過前幾個skip ~~~ Stream<T> skip(long n); ~~~ 如果流的長度大于n,則跳過n個.否則將會得到一個長度為0的空流 ### 排序sorted sorted有2個,無參和有參數(定制的) ~~~ //此時針對Employees進行排序:失敗。原因:Employee類沒有實現Comparable接口 // List<Employee> list1 = EmployeeData.getEmployees(); // list1.stream().sorted().forEach(System.out::println); // sorted(Comparator com)——定制排序 List<Employee> list1 = EmployeeData.getEmployees(); list1.stream().sorted((e1,e2) -> { if(e1.getAge() != e2.getAge()){ return e1.getAge() - e2.getAge(); }else{ return -Double.compare(e1.getSalary(),e2.getSalary()); } }).forEach(System.out::println); ~~~ ## 遇到不符合條件就終止talkWhile 從流中一直獲取判定器為真的元素,一旦遇到元素為假,就終止處理,后面就不處理了 ~~~ Stream<Integer> stream = Stream.of(3, 9, 7, 1, 10, 11); Stream<Integer> integerStream = stream.takeWhile(t -> t % 2 != 0); integerStream.forEach(System.out::print); ~~~ 輸出 3971 ## 遇到不合適的就丟棄dropWhile 只要為真的就一直丟棄,直到遇見為假的,就終止處理,后面就不處理了 ~~~ Stream<Integer> stream = Stream.of(3, 9, 7, 1, 6, 11); Stream<Integer> integerStream = stream.dropWhile(t -> t % 2 != 0); integerStream.forEach(System.out::print); ~~~ 輸出 611
                  <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>

                              哎呀哎呀视频在线观看