Cara mengintip () dan allMatch () bekerja bersama di Java 8 Stream API

10

Saya menemukan kuis tentang Java 8 Stream API metode mengintip seperti di bawah ini

Arrays.asList("Fred", "Jim", "Sheila")
      .stream()
      .peek(System.out::println)
      .allMatch(s -> s.startsWith("F"));

Outputnya adalah

Fred
Jim

Saya bingung bagaimana aliran ini berfungsi? Hasil yang saya harapkan seharusnya

Fred
Jim
Sheila

Metode peek () adalah operasi perantara dan memproses setiap elemen dalam Stream. Adakah yang bisa menjelaskan ini padaku.

Barcelona
sumber

Jawaban:

10

Ini adalah optimasi aliran yang dikenal sebagai hubungan arus pendek. Pada dasarnya, apa yang terjadi adalah yang allMatchmencegah pelaksanaan operasi perantara yang tidak perlu di arus, karena tidak ada gunanya menjalankannya ketika hasil akhirnya diketahui.

Seolah-olah ini terjadi:

take"Fred"
peek("Fred")
evaluate("Fred".startsWith("F"))
decide whether the result of allMatch() is known for sure: Not yet

take"Jim"
peek("Jim")
evaluate("Jim".startsWith("F"))
decide whether the result of allMatch() is known for sure: Yes

Ketika "Jim".startsWith("F")dievaluasi, hasilnya allMatch(s -> s.startsWith("F"))diketahui pasti. Tidak masalah nilai apa yang datang dalam pipa setelahnya "Jim", kita tahu bahwa semua nilai dimulai dengan "F" salah

Ini bukan khusus untuk peek/ allMatchkombinasi, ada beberapa operasi hubungan arus pendek menengah dan terminal. Status java.util.streamdokumen paket :

Lebih lanjut, beberapa operasi dianggap sebagai hubungan arus pendek. Operasi perantara adalah hubungan arus pendek jika, ketika disajikan dengan input tak terbatas, itu dapat menghasilkan aliran terbatas sebagai hasilnya. Suatu operasi terminal adalah hubungan arus pendek jika, ketika disajikan dengan input yang tak terbatas, itu dapat berakhir dalam waktu yang terbatas. Memiliki operasi hubungan arus pendek dalam pipa adalah kondisi yang diperlukan, tetapi tidak cukup, untuk pemrosesan aliran tak terbatas untuk berakhir secara normal dalam waktu yang terbatas.

Perluas ini hingga aliran terbatas, dan operasi hubungan arus pendek menghindarkan pelaksanaan langkah-langkah pipa yang tidak perlu, seperti dalam contoh Anda.

ernest_k
sumber
5
Arrays.asList("Fred", "Jim", "Sheila")
      .stream()
      .peek(System.out::println)
      .allMatch(s -> s.startsWith("F"));
  • Pertama kali melalui, Freddicetak. Sangat cocok
  • Kedua kalinya, Jimdicetak. Itu tidak cocok sehingga semua pertandingan berakhir karena "Semua tidak cocok"
  • Jadi item terakhir tidak dikonsumsi dari aliran.
WJS
sumber
3

The docs untuk peekmetode katakanlah (penekanan):

Mengembalikan aliran yang terdiri dari elemen-elemen aliran ini, selain itu melakukan tindakan yang disediakan pada setiap elemen saat elemen dikonsumsi dari aliran yang dihasilkan .

Jadi dalam kasus ini, peektidak melihat "Sheila"karena nilai itu tidak dikonsumsi dari aliran. Segera setelah "Jim"dikonsumsi, hasilnya .allMatch(s -> s.startsWith("F"))sudah diketahui false, jadi tidak perlu lagi mengkonsumsi elemen dari sungai.

kaya3
sumber
1

Sesuai Java Doc Of allMatch ():

Mengembalikan apakah semua elemen aliran ini cocok dengan predikat yang disediakan. Mungkin tidak mengevaluasi predikat pada semua elemen jika tidak perlu untuk menentukan hasilnya. Jika aliran kosong maka {@code true} dikembalikan dan predikat tidak dievaluasi.

@apiNote

Metode ini mengevaluasi kuantifikasi universal dari predikat atas elemen-elemen aliran (untuk semua x P (x)). Jika aliran kosong, kuantifikasi dikatakan puas kosong dan selalu {@code true} (terlepas dari P (x)).

predikat untuk diterapkan ke elemen aliran ini @ return {@code true} jika semua elemen aliran cocok dengan predikat yang disediakan atau aliran kosong, jika tidak {@code false}

Dalam kasus Anda:

1-

p(x) : s -> s.startsWith("F")

X : "Fred"

result : X P(X) = true

2-

p(x) : s -> s.startsWith("F")

X : "Jim"

result : X P(X) = false

Tidak ada evaluasi lebih lanjut yang akan dilakukan, karena XP (X) = false

boolean result = Arrays.asList("Fred", "Finda", "Fish")
            .stream()
            .peek(System.out::println)
            .allMatch(s -> s.startsWith("F"));
    System.out.println("Result "+result);

Output adalah:

Fred
Finda
Fish
Result true

Di sini aliran diproses sepenuhnya karena xP (x) = true dari setiap elemen

Sandeep Tiwari
sumber