Java8 學(xué)習(xí)筆記(二)——Stream流

1.簡(jiǎn)單使用

Arrays.asList(1, 4, 2, 3, 5, 6, 7, 9, 0, 8)
      .stream()
      .sorted()// 排序
      .filter(x -> x > 3)// 過(guò)濾
      .forEach(System.out::print);

運(yùn)行結(jié)果:
4,5,6,7,8,9


  • Stream(流)和InputStream/OutputStream并沒(méi)有關(guān)系
  • Stream提供了很多Lambda表達(dá)式方法
  • 重點(diǎn)在于對(duì)數(shù)組的操作

特點(diǎn):

  1. Stream不存儲(chǔ)數(shù)據(jù)
  2. Stream不會(huì)修改源數(shù)據(jù),無(wú)論怎么操作源數(shù)據(jù)并不會(huì)改變
  3. Stream是單向的,不可以重復(fù)使用
  4. Stream的部分操作是延遲的
  • 只要Stream的方法返回的對(duì)象是Stream,這些方法就是延遲執(zhí)行的方法
  • 延遲執(zhí)行的方法,一定要等到一個(gè)迫切方法執(zhí)行的時(shí)候,才會(huì)執(zhí)行。一般在Stream流中,一個(gè)方法返回的不是Stream,基本就是迫切方法
  1. Stream可以執(zhí)行并行操作

2.創(chuàng)建Stream

數(shù)組和集合創(chuàng)建Stream流方法不一樣


2.1數(shù)組創(chuàng)建Stream

一般可以通過(guò):Arrays.stream()Stream.of()

int [] ints = new int[]{1,3,4,2,5};
IntStream intStream= Arrays.stream(ints);
intStream.forEach(System.out::print);

運(yùn)行結(jié)果:13425


注意:不能直接把簡(jiǎn)單數(shù)據(jù)類(lèi)型的數(shù)組直接作為Stream.of()的參數(shù)

int [] ints = new int[]{1,3,4,2,5};
Stream<int[]>stream= Stream.of(ints);
stream.forEach(System.out::print);```
運(yùn)行結(jié)果為:
`[I@1218025c`
***
```java
Stream<Integer>stream2 = Stream.of(1,3,4,2,5);
stream2.sorted().forEach(System.out::print);

運(yùn)行結(jié)果為:
12345

Stream<Integer>IntStream不是同一個(gè)對(duì)象


2.2集合創(chuàng)建Stream

集合可以通過(guò):集合對(duì)象.stream()

List<Integer>list = (List<Integer>) Arrays.asList(1,2,4,3,5);
Stream<Integer>stream = list.stream();

2.3創(chuàng)建并行Stream

通過(guò)集合對(duì)象.parallelStream()

List<Integer>list = (List<Integer>) Arrays.asList(1,2,4,3,5);
Stream<Integer>stream = list.parallelStream();

2.4 創(chuàng)建大量數(shù)據(jù)的Stream

  • 初始化一個(gè)無(wú)限重復(fù)字符串的Stream
Stream.generate(()->"Hello World!!!").forEach(System.out::println);

運(yùn)行結(jié)果:
無(wú)限打印出Hello World!!!


  • 初始化一個(gè)有限的數(shù)據(jù)的Stream

可以通過(guò)limit()方法來(lái)限制創(chuàng)建數(shù)據(jù)的數(shù)量

Stream.generate(()->"Hello World !!!").limit(5).forEach(System.out::println);

運(yùn)行結(jié)果:
打印出5個(gè)Hello World!!!


2.5創(chuàng)建一個(gè)規(guī)律數(shù)據(jù)的Stream

例如,創(chuàng)建一個(gè)從開(kāi)始1到10的數(shù)列的Stream

Stream.iterate(1, x -> x +1).limit(10).forEach(System.out::print);

運(yùn)行結(jié)果:12345678910

iterate()方法中,有兩個(gè)參數(shù),第一個(gè)為初始數(shù)據(jù),第二個(gè)為一個(gè)Operator接口

Stream.iterate("a", UnaryOperator.identity()).limit(10).forEach(System.out::print);

運(yùn)行結(jié)果:aaaaaaaaaa
UnaryOperator.identity()自己返回自己


3.Stream常見(jiàn)的操作

  • 過(guò)濾操作filter,distinct
  • 變換操作map,flatMap
  • 拆分合并流操作limit,skip,concat,peek
  • 排序操作sorted,unordered

操作符方法內(nèi)往往需要一個(gè)函數(shù)式接口

Java8函數(shù)式接口

3.1過(guò)濾操作

  • filter
    例:找出所有開(kāi)頭為大寫(xiě)字母的字符串
Arrays.asList("Abc","Bc","ac","op","IQ")
        .stream()
        .filter(s->Character.isUpperCase(s.charAt(0)))
        .forEach(System.out::println);

運(yùn)行結(jié)果:
Abc Bc IQ

  • distinct去除重復(fù)元素
Arrays.asList("a","c","ac","c","a","b")
        .stream()
        .distinct()
        .forEach(System.out::println);

運(yùn)行結(jié)果:
a c ac b


3.2變換操作

  • map

把一種類(lèi)型的Stream變?yōu)榱硪环N類(lèi)型的Stream,map方法內(nèi)需要一個(gè)Function接口,Function<? super String, ? extends String> mapper

例:將字符串全部變?yōu)榇髮?xiě)

Arrays.asList("hdfa","adfc","aedc","yui")
      .stream()
      .map(s->s.toUpperCase()+" ,")
      .forEach(System.out::print);

運(yùn)行結(jié)果:
HDFA ,ADFC ,AEDC ,YUI ,

  • flatMap

flatMap方法也需要Function接口,只是Function接口的泛型不同,Function<? super T, ? extends Stream<? extends R>> mapper,返回的是Stream對(duì)象

private static void flatMapStream() {
    String [] strs1 = {"a","b","c"};
    String [] strs2 = {"d","e","f"};
    String [] strs3 = {"a","g","h"};
    Arrays.asList(strs1,strs2,strs3)
          .stream()
          .flatMap(str -> Stream.of(str))
          .map(s -> s+",")
          .forEach(System.out::print);
    }

運(yùn)行結(jié)果:
a,b,c,d,e,f,a,g,h,

flatMap是把高緯度流變?yōu)榈途暥攘鳌?/p>

flatmap變換

str1,str2,str3作為Stream<String[]>中的元素,可以看做是二維的數(shù)組,經(jīng)過(guò)flatMap變換,Stream<String[]>就變?yōu)榱?code>Stream<String>,由二維變?yōu)榱艘痪S。


3.3拆分合并流操作

  • limit

限制,返回 Stream 的前面 n 個(gè)元素

Arrays.asList(1,2,3,4,5)
      .stream()
      .limit(3)
      .forEach(System.out::print);

運(yùn)行結(jié)果:123

  • skip

跳過(guò)Stream前的n個(gè)元素

Arrays.asList(1,2,3,4,5)
      .stream()
      .skip(2)
      .forEach(System.out::print);

運(yùn)行結(jié)果:345

  • concat

static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
將兩個(gè)Stream合并成一個(gè),這個(gè)方法一次只能用來(lái)合并兩個(gè)Stream,不能一次多個(gè)Stream合并。

private static void concatStream() {
    Stream<Integer>stream1=Arrays.asList(1,2,3).stream();
    Stream<String>stream2=Arrays.asList("a","b","c").stream();
    Stream.concat(stream1,stream2).forEach(System.out::print);
}

運(yùn)行結(jié)果:123abc


3.4流的排序

sorted()方法是個(gè)元素相關(guān)的方法,和整體的數(shù)據(jù)有關(guān)系。

  • sorted(),無(wú)參方法
Arrays.asList(3,1,4,5,2)
      .stream()
      .sorted()
      .forEach(System.out::print);

運(yùn)行結(jié)果:123456
使用sorted()這個(gè)方法,要求Stream中的數(shù)據(jù)必須實(shí)現(xiàn)了Comparable接口

  • sorted(Comparator< ? super T > comparator)
    例:按照字符串長(zhǎng)度進(jìn)行排序
Arrays.asList("ae","f","gqet","ertyu","zxc")
        .stream()
        .sorted((s1,s2)-> Integer.compare(s1.length(), s2.length()))
        .forEach(System.out::println);

運(yùn)行結(jié)果:
f ae zxc gqet ertyu


若兩個(gè)字符串長(zhǎng)度相同,按照字母順序排列,可以用ComparatorthenComparaimg()

Arrays.asList("ae", "f", "gqet", "abcd", "ertyu", "zxc")
      .stream()
      .sorted(
               Comparator.comparing(String::length)
                         .thenComparing(String::compareTo)
             )
      .forEach(System.out::println);

運(yùn)行結(jié)果:
f ae zxc abcd gqet ertyu


反轉(zhuǎn)排序:Comparatorreversed()

//數(shù)字
Arrays.asList(2,3,4,1,5)
      .stream()
      .sorted(Comparator.reverseOrder())
      .forEach(System.out::print);
//字符串
Arrays.asList("ae", "f", "gqet", "abcd", "ertyu", "zxc")
      .stream()
      .sorted(Comparator.comparing(String::length).reversed())
      .forEach(System.out::println);

如果Comparator.comparing()方法中是非方法引用的Lambda表達(dá)式,就無(wú)法直接使用.reversed()


parallel().sorted()之后,不能直接使用forEach(),要使用forEachOrdered()。并行Stream和sorted()并不會(huì)沖突。

使用forEach()

Arrays.asList(1,4,5,2,3,6,8,9,7)
      .stream()
      .parallel()
      .sorted()
      .forEach(System.out::print);

運(yùn)行結(jié)果:378692415

使用forEachOrdered():

Arrays.asList(1,4,5,2,3,6,8,9,7)
      .stream()
      .parallel()
      .sorted()
      .forEachOrdered(System.out::print);

運(yùn)行結(jié)果:123456789


4.Stream的結(jié)果處理

  • 遍歷forEach
  • 聚合reduce
  • Optional類(lèi)型
  • 收集collect

4.1聚合reduce

reduce()可以實(shí)現(xiàn)從一組數(shù)據(jù)中生成一個(gè)數(shù)據(jù),這個(gè)方法有三種形式:

  • Optional<T> reduce(BinaryOperator<T> accumulator)
  • T reduce(T identity, BinaryOperator<T> accumulator)
  • <U> U reduce(U identity,BiFunction<U,? super T,U> accumulator,BinaryOperator<U> combiner)

例:求累加和

Arrays.asList(1,2,3)
      .stream()
      .reduce((sum,i)-> sum = sum+i)
      .ifPresent(System.out::print);

4.2Optional

Optional是一種容器,可以存儲(chǔ)一些值和null。利用這個(gè)類(lèi),可以進(jìn)行null的判斷,能夠有效的避免NullPointerException

  • get(),可以拿到Optional中的值,沒(méi)有值則拋出空指針異常
  • isPresent(),有非空的值,返回true,否則返回false
  • ifPresent(),public void ifPresent(Consumer<? super T> consumer)這個(gè)方法中需要一個(gè)Consumer接口。如果有非空的值,就執(zhí)行指定的Consumer的方法來(lái)處理這個(gè)非空的值;如果為空,則啥都不做

reduce()操作返回的就是Optional


4.3收集collect

collect()可以將Stream流轉(zhuǎn)變成集合

List<Integer>list= Arrays.asList(1,2,3,4,5)
                         .stream()
                         .filter(i-> i>3)
                         .collect(Collectors.toList());
list.forEach(System.out :: print);

5.最后

Java8 常見(jiàn)的函數(shù)式接口多看看。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Int Double Long 設(shè)置特定的stream類(lèi)型, 提高性能,增加特定的函數(shù) 無(wú)存儲(chǔ)。stream不是一...
    patrick002閱讀 1,330評(píng)論 0 0
  • Streams 原文鏈接: Streams 原文作者: shekhargulati 譯者: leege100 狀態(tài)...
    忽來(lái)閱讀 5,611評(píng)論 3 32
  • 前言: 講Stream之前,先來(lái)用個(gè)小需求帶入本文。畢竟代碼看的最清楚。 正文: 項(xiàng)目某個(gè)頁(yè)面有個(gè)需求,將關(guān)鍵詞和...
    T9的第三個(gè)三角閱讀 2,480評(píng)論 1 9
  • Jav8中,在核心類(lèi)庫(kù)中引入了新的概念,流(Stream)。流使得程序媛們得以站在更高的抽象層次上對(duì)集合進(jìn)行操作。...
    仁昌居士閱讀 4,081評(píng)論 0 6
  • 從不稱(chēng)呼你的名字 愿意借以各種秘密的代號(hào) 有時(shí)是一種動(dòng)物或音調(diào) 有時(shí)是一個(gè)名詞或形容詞 也可以是語(yǔ)氣詞 這是一種快...
    鼠想說(shuō)的閱讀 637評(píng)論 20 19

友情鏈接更多精彩內(nèi)容