溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何使用Java 8 Stream和peek

發(fā)布時(shí)間:2020-07-31 10:20:49 來(lái)源:億速云 閱讀:160 作者:小豬 欄目:編程語(yǔ)言

這篇文章主要講解了如何使用Java 8 Stream和peek,內(nèi)容清晰明了,對(duì)此有興趣的小伙伴可以學(xué)習(xí)一下,相信大家閱讀完之后會(huì)有幫助。

簡(jiǎn)介

java 8 stream作為流式操作有兩種操作類型,中間操作和終止操作。這兩種有什么區(qū)別呢?

我們看一個(gè)peek的例子:

Stream<String> stream = Stream.of("one", "two", "three","four");
stream.peek(System.out::println);

上面的例子中,我們的本意是打印出Stream的值,但實(shí)際上沒有任何輸出。

為什么呢?

中間操作和終止操作

一個(gè)java 8的stream是由三部分組成的。數(shù)據(jù)源,零個(gè)或一個(gè)或多個(gè)中間操作,一個(gè)或零個(gè)終止操作。

中間操作是對(duì)數(shù)據(jù)的加工,注意,中間操作是lazy操作,并不會(huì)立馬啟動(dòng),需要等待終止操作才會(huì)執(zhí)行。

終止操作是stream的啟動(dòng)操作,只有加上終止操作,stream才會(huì)真正的開始執(zhí)行。

所以,問題解決了,peek是一個(gè)中間操作,所以上面的例子沒有任何輸出。

peek

我們看下peek的文檔說(shuō)明:peek主要被用在debug用途。

我們看下debug用途的使用:

Stream.of("one", "two", "three","four").filter(e -> e.length() > 3)
        .peek(e -> System.out.println("Filtered value: " + e))
        .map(String::toUpperCase)
        .peek(e -> System.out.println("Mapped value: " + e))
        .collect(Collectors.toList());

上面的例子輸出:

Filtered value: three
Mapped value: THREE
Filtered value: four
Mapped value: FOUR

上面的例子我們輸出了stream的中間值,方便我們的調(diào)試。

為什么只作為debug使用呢?我們?cè)倏匆粋€(gè)例子:

Stream.of("one", "two", "three","four").peek(u -> u.toUpperCase())
.forEach(System.out::println);

上面的例子我們使用peek將element轉(zhuǎn)換成為upper case。然后輸出:

one
two
three
four

可以看到stream中的元素并沒有被轉(zhuǎn)換成大寫格式。

再看一個(gè)map的對(duì)比:

Stream.of("one", "two", "three","four").map(u -> u.toUpperCase())
.forEach(System.out::println);

輸出:

ONE
TWO
THREE
FOUR

可以看到map是真正的對(duì)元素進(jìn)行了轉(zhuǎn)換。

當(dāng)然peek也有例外,假如我們Stream里面是一個(gè)對(duì)象會(huì)怎么樣?

  @Data
  @AllArgsConstructor
  static class User{
    private String name;
  }

    List<User> userList=Stream.of(new User("a"),new User("b"),new User("c")).peek(u->u.setName("kkk")).collect(Collectors.toList());
    log.info("{}",userList);

輸出結(jié)果:

10:25:59.784 [main] INFO com.flydean.PeekUsage - [PeekUsage.User(name=kkk), PeekUsage.User(name=kkk), PeekUsage.User(name=kkk)]

我們看到如果是對(duì)象的話,實(shí)際的結(jié)果會(huì)被改變。

為什么peek和map有這樣的區(qū)別呢?

我們看下peek和map的定義:

Stream<T> peek(Consumer<&#63; super T> action)
<R> Stream<R> map(Function<&#63; super T, &#63; extends R> mapper);

peek接收一個(gè)Consumer,而map接收一個(gè)Function。

Consumer是沒有返回值的,它只是對(duì)Stream中的元素進(jìn)行某些操作,但是操作之后的數(shù)據(jù)并不返回到Stream中,所以Stream中的元素還是原來(lái)的元素。

而Function是有返回值的,這意味著對(duì)于Stream的元素的所有操作都會(huì)作為新的結(jié)果返回到Stream中。

這就是為什么peek String不會(huì)發(fā)生變化而peek Object會(huì)發(fā)送變化的原因。

看完上述內(nèi)容,是不是對(duì)如何使用Java 8 Stream和peek有進(jìn)一步的了解,如果還想學(xué)習(xí)更多內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI